K 次取反后最大化的数组和
# 📃 题目描述
题目链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)
给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:
- 选择某个下标 i 并将 nums[i] 替换为 -nums[i]
- 重复这个过程恰好 k 次。可以多次选择同一个下标 i
以这种方式修改数组后,返回数组 可能的最大和
示例 1:
输入:nums = [4,2,3], k = 1
输出:5
解释:选择下标 1 ,nums 变为 [4,-2,3]
示例 2:
输入:nums = [3,-1,0,2], k = 3
输出:6
解释:选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2]
示例 3:
输入:nums = [2,-3,-1,5,-4], k = 2
输出:13
解释:选择下标 (1, 4) ,nums 变为 [2,3,-1,5,4]
# 🔔 解题思路
这里有两个贪心思想:
1)优先选择绝对值大的负数进行取反
2)如果负数全部取反后 k 还是大于 0:
- k 为偶数,则直接返回结果就行了(比如 nums = [3,-1,0,2], k = 3,负数全部取反后,k = 2,此时 nums = [3, 1, 0, 2], nums 全部为正数的情况就是能够得到的最大和,此时我们只需要对任意一个数取反两次即保持不变就行)
- k 为奇数,则对最小的这个正数取反奇数次(即把最小的正数变为负数)
Comparator
只支持引用类型,对于 int[] 类型的数组,是没有办法直接传进去的,需要转成 Integer 类型数组。可以用 Stream 流来简化操作
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
if (nums == null || nums.length == 0) {
return 0;
}
// 按照绝对值大小降序排序
// IntStream.of() 填充一个或多个int元素构造流
// IntStream.boxed() 方法返回一个由该流元素组成的 Stream,每个元素都装箱为一个 Integer
// mapToInt 使用映射函数处理流中的每一个元素, 并返回一个新的 IntStream
nums = IntStream.of(nums).boxed().sorted(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Math.abs(o2) - Math.abs(o1);
}
}).mapToInt(Integer::intValue).toArray();
// 优先取反绝对值大的负数
for (int i = 0; i < nums.length; i ++) {
if (nums[i] < 0 && k > 0) {
nums[i] *= -1;
k --;
}
}
// 如果负数全部取反后 k 还是大于 0
if (k % 2 == 1) {
// k 为奇数,则对最小的这个正数取反奇数次(即把最小的正数变为负数)
nums[nums.length - 1] *= -1;
}
// k 为偶数或者 k == 0,则直接返回结果就行了
return Arrays.stream(nums).sum();
}
}
# 💥 复杂度分析
- 空间复杂度:O(1)
- 时间复杂度:O(NLogN),主要是排序的耗时
🎁 公众号

各位小伙伴大家好呀,叫我小牛肉就行,目前在读东南大学硕士,上方扫码关注公众号「飞天小牛肉」,与你分享我的成长历程与技术感悟~
帮助小牛肉改善此页面 (opens new window)
Last Updated: 2023/02/16, 11:27:10