Java- K 次取反后最大化的数组和
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java- K 次取反后最大化的数组和相关的知识,希望对你有一定的参考价值。
题目描述
题目来源:LeetCode1005
给定一个整数数组 A,我们只能用以下方法修改该数组:
我们选择某个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)
以这种方式修改数组后,返回数组可能的最大和。
算法分析
考虑贪心的最优策略:
我们必须经历 K 次取反操作,因此,为了使我们的数组和维持最大,我们可以将所有负数取反,若最后 K 还有剩余,可当前所有数已经为大于等于0,没有其他选择,则只能将 最小的数 取反剩余次数。
代码展示
桶排序
数值范围 -100~100,因此考虑创建数组大小 200,其中 0 代表-100,100代表 0,200代表100。
将 数值+100 映射到 0~200
class Solution {
public int largestSumAfterKNegations(int[] A, int K) {
int[] number = new int[201]; // -100 <= A[i] <= 100,这个范围的大小是201
for (int t : A) {
number[t + 100]++; // 将[-100,100]映射到[0,200]上
}
int i = 0;
while (K > 0) {
while (number[i] == 0) // 找到A[]中最小的数字
i++;
number[i]--; // 此数字个数-1
number[200 - i]++; // 其相反数个数+1
if (i > 100) { // 若原最小数索引>100,则新的最小数索引应为200-i.(索引即number[]数组的下标)
// 即原来最小值是正数,求反后变为负数,同时也是当前最小值
i = 200 - i;
}
K--;
}
int sum = 0;
for (int j = i; j <number.length ; j++) { // 遍历number[]求和
sum += (j-100)*number[j]; // j-100是数字大小,number[j]是该数字出现次数.
}
return sum;
}
}
贪心算法
- 按照绝对值从大到小排序,注意要按照绝对值的大小
- 从前向后遍历,遇到负数将其变为正数,同时 K–
- 注意遍历同时求和
- 如果 K 还大于0,那么反复转变数值最小的元素,将 K 用完
- K是偶数次就不用管,奇数次的话只用减去一次最小值即可。
class Solution:
def largestSumAfterKNegations(self, A: List[int], K: int) -> int:
# 将整数按照绝对值排序,降序
A = sorted(A, key=lambda a: abs(a), reverse=True)
# 从前向后找如果遇到负数直接取反,K--
ans = 0
for i in range(len(A)):
if A[i] < 0 and K > 0:
A[i] = -A[i]
K -= 1
ans += A[i]
# 如果最后剩余 K是奇数,只用将和-取最小的数的反
# 偶数就不用管,两次取反和相当于 0
if K % 2 == 1:
ans -= 2 * A[len(A)-1]
return ans
感谢LeetCode大佬代码!
加油!
以上是关于Java- K 次取反后最大化的数组和的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode1005 K次取反后最大化的数组和(贪心+Java简单排序)