持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 6 天,点击查看活动详情
题目链接
1005. K 次取反后最大化的数组和 - 力扣(LeetCode)
题目描述
给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:
选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。
以这种方式修改数组后,返回数组 可能的最大和 。
测试用例
示例 1:
输入: nums = [4,2,3], k = 1
输出: 5
解释: 选择下标 1 ,nums 变为 [4,-2,3] 。
限制
1 <= nums.length <= 104-100 <= nums[i] <= 1001 <= k <= 104
题目分析
题目,需要我们为一个包含了正负数的数组进行求和;同时,在求和之前,需要对数组的元素做 k 次取反操作
考虑到数组中的正数和负数参合在一起,那么,对 k 的值,需要分如下几种情况考虑:
k小于等于数组中负数的个数m时,此时,只需要将负数数组中,最小的k个值反转并求和即可k大于数组中负数的个数m时,我们需要将所有的负数反转,并且需要记录下,此时,数组中最小的数x,然后对x重复k-m次取反即可
为了方便计算,我们可以将数组 numns 过滤一次拿到他的全部的负数数组 arr,对 nums 求和标记为 sum,对 arr 求和并取标记为 diffVal,最后根据 k 相对 arr.length 的大小,进行两个值的合并即可;当处于 情况2 的时候,额外处理一下数组的最小值即可
代码实现
完整的代码实现如下
var largestSumAfterKNegations = function (nums, k) {
let sum = nums.reduce((prev, curr) => prev + curr, 0);
let min = nums.map(n => Math.abs(n)).reduce((a, b) => a > b ? b : a);
let arr = nums.filter(n => n < 0);
let diff = arr.length - k;
let diffVal = arr.sort((a, b) => a - b).slice(0, k).reduce((prev, curr) => prev + curr, 0);
if (arr.length == 0) {
return k % 2 == 0 ? sum : (sum - min * 2);
} else if (diff >= 0 || diff % 2 == 0) {
return sum + diffVal * -2;
} else {
return sum + diffVal * -2 - min * 2;
}
};