给定一个正整数数组,我可以减少任何数量的元素,使所有剩余的非零元素相等。
我必须找到最小值,它是所有减少的总和。
EX:1 1 1 1 2
答案:1(仅将最后一个元素减少1)。
EX:25 23 1 2
Ans:5(一种可能的方法是减少25到23,减少1到0,减少2到0.在所有减少操作数组之后是23 23 0 0,其中所有非零元素都相等。)
我尝试了在数组中找到最小值的方法,然后将所有其他元素等同于此。但是这种方法在第二种情况下失败了。对此的任何帮助都非常感谢。
答案 0 :(得分:2)
您的方法很好,但您需要考虑更多目标价值的选择。
它可以是数组中的任何值,因此只需依次尝试所有这些值。这将是一个O(n ^ 2)算法。
如果您想加快速度,可以先对条目进行排序。然后,您可以依次轻松计算每个目标值的成本(因为您知道需要将当前位置之前的所有元素减少到0,并将当前位置之后的所有元素减少到目标值,因此总成本是所有元素减去当前值乘以超出当前位置的元素数量
答案 1 :(得分:0)
你的方法听起来不错,但有很大的缺陷,并且不会一直有效。如果没有选项将数字等于零,它将起作用。在这个问题场景中,对于每个候选者,你应该计算通过将所有较大的数字等于该候选者而将所有较小的数字等于零而获得的差异总和,并查看哪个候选者具有最小的差异总和。
这是算法......
整体复杂性为 O(n log n),这里有一些代码......
private static int getMinimumDifference(int[] arr) {
int n = arr.length;
for (int i = 0; i < n; i++) {
if (arr[i] < 0) {
return -1;
}
}
if (n == 1)
return 0;
int left[] = new int[n];
int right[] = new int[n];
Arrays.sort(arr);
int tempSum = 0;
for (int i = 0; i < n; i++) {
left[i] = tempSum;
tempSum += arr[i];
}
tempSum = 0;
for (int i = n - 1; i >= 0; i--) {
right[i] = tempSum;
tempSum += arr[i];
}
int minDiff = tempSum, index = -1;
for (int i = 0; i < n; i++) {
int diff = 0;
diff += left[i]; // All numbers on the left reduced to 0
diff += right[i] - (arr[i] * (n - i - 1)); // All numbers on the right reduced to arr[i]
if (diff < minDiff) {
minDiff = diff;
index = i;
}
}
System.out.println("Minimum difference is " + minDiff + " and all numbers should be " + (index >= 0 ? arr[index] : "unknown"));
return minDiff;
}