Leetcode453. 最小移动次数使数组元素相等
题目:
给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数。每次移动可以使 n - 1 个元素增加 1。
示例:
输入:
[1,2,3]
输出:
3
解释:
只需要3次移动(注意每次移动会增加两个元素的值):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
题解:
方案一:暴力计算
时间复杂度:
:其中
为数组长度,
为最大值和最小值的差。
空间复杂度:
:不需要额外空间。
1.先循环遍历一次,找到最大值和最小值对应的数组下标;
2.如果最大值等于最小值,跳出整体循环;
3.再次循环遍历,对除了数组最大值的其他元素均加一;
4.计数器加1;
5.重复这一过程直到最大元素和最小元素相等。
方案二:暴力法优化
时间复杂度:
。每次迭代中两个元素是相等的。
空间复杂度:
。不需要额外空间。
在上一方法中,每一步对每个元素增加 1。我们可以在一定程度上改进这一方法。为了让最小元素等于最大元素,至少需要加
次。在那之后,最大元素可能发生变化。因此,我们一次性增加增量
,并将移动次数增加
。然后,对整个数组进行扫描,找到新的最大值和最小值,重复这一过程直到最大元素和最小元素相等。
方案三:逆向思维
时间复杂度:
。对数组进行了一次遍历。
空间复杂度:
。不需要额外空间。
给
个数加1相当于给余下的数减1,显然,我们只需要将所有的数都减到最小的数即可,
方案四:逆向思维优化
时间复杂度:
。一次遍历寻找最小值,一次遍历计算次数。
空间复杂度:
。不需要额外空间。
上一个方法可能存在问题。
可能会非常大,造成整数越界。为了避免这一问题,我们可以即时计算
scala代码:
/**
* 暴力法
*
* @param nums
* @return
*/
def minMoves(nums: Array[Int]): Int = {
var count = 0
var min = 0
var max = nums.length - 1
breakable(
while (true) {
for (i <- 0 until nums.length) {
if (nums(i) > nums(max)) {
max = i
}
if (nums(i) < nums(min)) {
min = i
}
}
if (nums(min) == nums(max)) {
break()
}
for (i <- 0 until nums.length) {
if (i != max) {
nums(i) = nums(i) + 1
}
}
count = count + 1
}
)
count
}
/**
* 暴力法优化
*
* @param nums
* @return
*/
def minMoves2(nums: Array[Int]): Int = {
java.util.Arrays.sort(nums)
var count = 0
var min = 0
var max = nums.length - 1
breakable(
while (true) {
for (i <- 0 until nums.length) {
if (nums(i) > nums(max)) {
max = i
}
if (nums(i) < nums(min)) {
min = i
}
}
val diff = nums(max) - nums(min)
if (diff == 0) {
break()
}
count = count + diff
for (i <- 0 until nums.length) {
if (i != max) {
nums(i) = nums(i) + diff
}
}
}
)
count
}
/**
* 逆向思维
* 给n-1个数加1相当于给剩下的一个数减1
*
* @param nums
* @return
*/
def minMoves3(nums: Array[Int]): Int = {
var count = 0
var min = Int.MaxValue
for (i <- 0 until nums.length) {
count = count + nums(i)
min = math.min(min, nums(i))
}
count - min * nums.length
}
/**
*逆向思维优化
* @param nums
* @return
*/
def minMoves4(nums: Array[Int]): Int = {
var count = 0
var min = Int.MaxValue
for (i <- 0 until nums.length) {
min = math.min(min, nums(i))
}
for (i <- 0 until nums.length) {
count = count + (nums(i) - min)
}
count
}