给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数。每次移动可以使 n - 1 个元素增加 1。
示例:
输入:
[1,2,3]
输出:
3
解释:
只需要3次移动(注意每次移动会增加两个元素的值):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
尴尬了,这样的算法肯定会超时啊,所以有些题目你需要将题目变个意思,或者利用归纳法得出一个比较简单的解法,这样就简单了
class Solution {
public int minMoves(int[] nums) {
int count = 0;
if(nums.length == 0 || nums.length == 1){
return 0;
}
if(nums.length == 2){
return nums[1] - nums[0] > 0? nums[1] - nums[0]:nums[0] - nums[1];
}
//Arrays.sort(nums);
while (!isEqual(nums)) {
Arrays.sort(nums);
int tem = nums[nums.length - 1] - nums[nums.length - 2];
int j = nums.length - 1;
while (tem == 0) {
tem = nums[j-1] - nums[j-2];
j--;
}
//System.out.println(tem);
count+= tem;
for (int i = 0; i < nums.length-1; i++) {
// System.out.println(nums[i]+"自增啦");
nums[i] +=tem;
}
}
return count;
}
public static boolean isEqual(int []nums){
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0)+1);
}
if(map.size() == 1){
return true;
}else {
return false;
}
}
}
逆向思考,每次移动让剩余的n-1个数加1,相当于每次移动让选定的那个数减1,
所以最少移动次数其实就是所有元素减去最小元素的和可以改成这样的算法,那样就比较简单了
class Solution {
public int minMoves(int[] nums) {
int min = Integer.MAX_VALUE;
int ref = 0;
for (int i = 0; i < nums.length; i++) {
min = Integer.min(min, nums[i]);
}
for (int i = 0; i < nums.length; i++) {
ref += nums[i]-min;
}
return ref;
}
}
排名靠前的算法
class Solution {
public int minMoves(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int min = Integer.MAX_VALUE;
int res = 0;
for (int i : nums) {
if (i < min) {
min = i;
}
res += i;
}
return res - min * nums.length;
}
}