/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
const numsToNumber = (nums) => {
if (nums.length === 0) {
return 0;
}
return nums.reduce((prev, next) => {
return prev + next;
});
};
var largestSumAfterKNegations = function (nums, k) {
if (nums.length === 0) {
return 0;
}
nums.sort((prev, next) => {
return prev - next;
});
const l1 = nums.filter((num) => { return num < 0 }).sort((prev, next) => {
return prev - next;
});
const t = k % 2 === 0;
// 考虑无复数的情况
if (l1.length === 0 && t) {
return numsToNumber(nums);
} else if (l1.length === 0 && !t) {
return numsToNumber(nums) - 2 * nums[0];
}
// 到这里开始考虑数组内有负数的情况
const t2 = (k - l1.length) <= 0; //考虑k与负数个数的关系
if (t2) {
return numsToNumber(nums.filter((num) => { return num >= 0 })) - numsToNumber(l1.slice(0, k)) + numsToNumber(l1.slice(k, l1.length));
}
const t3 = (k - l1.length) % 2 === 0; //k > l1.length
// t3
if (t3) {
return numsToNumber(nums.map((num) => { return Math.abs(num) }));
}
const l2 = nums.map((num) => { return Math.abs(num) }).sort((prev, next) => {
return prev - next;
});
return numsToNumber(l2) - 2 * l2[0];
};
思路:贪心算法
- 首先判断nums内有无负数(利用 l1 的长度来计算)以及k的奇偶性
- l1.length===0的情况下,如果k为偶数则自我抵消,对原数组无任何影响;若k为奇数则需要令nums的和减去两倍的nums中的最小值:
- 当l1.length>0时,我们首先考虑l1.length与k的差值大于等于0的特殊情况
- 接下来讨论l1.length < k的情况,此时如果(l1.length-k)%2===0,则k可以将l1中的负数全部取反,由于还会剩下偶数次取反的机会可以自我抵消(负负得正),因此我们只需要将nums全部取绝对值相加即可
- 若l1.length < k且(l1.length-k)%2!==0,则首先:
由上可知l2是nums经过取绝对值并排序过后的数组,在这种情况下由于我们必须做出“牺牲”,令l2之中最小的值消耗完取反次数,则此时这个最小值会为负数,我们需要的结果就是l2的总和减去2倍的该最小值:
ps.本人水平有限,欢迎批评指正