题目来源:https://leetcode-cn.com/problems/maximize-sum-of-array-after-k-negations/
大致题意:
给定一个数组 nums 和修改次数 k,每次修改都将数组的某一位取相反数,求出 k 次修改后数组可能的最大元素和
思路
先排序,然后从后往前(从最小的数开始)一个个取反
排序
- 先将数组升序排序
- 从后往前(从最小的数开始)把负数一个个取反,直到所有负数都为正数或者已经修改 k 次
- 此时判断修改次数是否用完,若未用完,那么判断 k 是否为奇数,为奇数代表还需要取反一个当前的最小数(最小数就在上一轮最后遍历位置的数和其前一个数之间);为偶数就不用管了(负负得正)。而若修改次数已经用完,也不用管了(已经尽可能的把最小的负数都变正了)
为什么最小数就在上一轮最后遍历位置的数和其前一个数之间?因为此时已经取反完毕,遍历到第一个非负数,而这个正数就是取反前的最小非负数,而前一个位置就是取反前的最大负数,也就是负数取反后的最小值,那么当前数组的最小值一定从它俩之间选出
给两个例子:
-6, -5, -1, 2, 3 修改次数为 4 那么最后就是将取反后的 1 再取反,因为 1 小于其右侧的 2
-6, -5, -2, 1, 3 修改次数为 4 那么最后就是将取反前最小的非负数 1 取反,因为 1 小于其左侧的 2(-2 取反的结果)
代码:
public int largestSumAfterKNegations(int[] nums, int k) {
Arrays.sort(nums); // 升序排序
int idx = 0;
int n = nums.length;
// 取反
// 注意边界
while (idx < n && nums[idx] < 0 && k > 0) {
nums[idx] = -nums[idx];
idx++;
k--;
}
// 如果遍历到最后一个位置,修改次数还未用完,为防止越界需要 -1
if (idx == n) {
idx--;
}
// 当修改次数未用完,且剩余次数为奇数
if (k > 0 && k % 2 == 1) {
// 将目前的最小值取反
if (idx > 0 && nums[idx] > nums[idx - 1]) {
nums[idx - 1] = -nums[idx - 1];
} else {
nums[idx] = -nums[idx];
}
}
return Arrays.stream(nums).sum();
}
该博客讨论了一种算法问题,即在给定数组和修改次数k的情况下,如何通过取反数组中的元素来最大化数组的和。解决策略是首先对数组进行升序排序,然后从最小的负数开始取反,直到所有负数变为正数或用完k次修改。如果k还有余数,且为奇数,则取反当前最小的数。举例说明了该策略的正确性,并提供了相应的Java代码实现。
562

被折叠的 条评论
为什么被折叠?



