题目:给你一个整数数组 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] 。
思考:
首先我想到的是当k为奇数时:
面对负数转换过就成为了正数,有利于数组的和的最大化
面对偶数时就会使数组和变小
其次当k为偶数时:
面对负数转换过仍然不变
面对偶数时也不会改变
那么,当数组里有负数时,应当优先把它变成正数 也就是进行奇数次的取反
可以初步确定的是数组中的负数越少越好(在改变次数不足的情况下优先改变更小的负数,使其成为更大的正数),即使在非改变正数不可的情况下,也是改变数值越小的正数越好
可是应该如何定位到该取反哪些数值呢?
也许我们可以先将数组按从小到大排序,之后再进行如下操作:
假设一:
一个包含正数和负数的数组,优先对更小的负数进行取反,依从小到大的次序将所有的负数都取反成为正数后,如果仍有取反次数,重新对数组进行排序(此时数组中应当不存在负数),从小到大排序,优先对更小的数进行取反,这么看来都是对更小的数进行操作,如果没有取反次数了那么就可以直接相加算总和了,这里再进一步考虑如果在初步进行取反的时候,取反次数已经用完了但仍然存在负数那也没关系,直接相加就是正确的总和了其实。
假设二:
一个全是正数的数组,因为其本身不做任何改变的情况下就已经是能得到的最大化的数组和的最优解了,所以我们在这里应当做到的就是尽量少的减少对数组的影响,从这一角度出发的话,在k为奇数的情况下,对最小的数进行操作,能做到最小的影响,在k为偶数的情况下就无所谓了,随便哪个元素都没关系,直接算总和就可以。
假设三:
一个全是负数的数组,先将其按照从小到大进行排序,对更小的值进行改变,在k值未消耗完之前完成了对整个数组的一遍取反,这个时候就从数组末尾,对最后一个元素进行反复操作就可以,还有一种情况时k值已经用完但仍然没有完成对整个数组的取反,但是没关系这种情况已经是最优解了。
但是感觉这种方法很麻烦而且弯弯绕绕,不知道有没有更优解😅
代码如下:
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
let nums = [2, -3, -1, 5, -4];
function sortNumber(a, b) {
return a - b;
}
var largestSumAfterKNegations = function (nums, k) {
let len = nums.length;
let sum = 0;
nums.sort(sortNumber);
// console.log(nums); 到这里完成了对数组的排序 那么接下来就按计划一步步来完成
//首先是k值不足以完成对全部负数的取反
/*
let k = 2;
for (let i = 0; i < k; i++) {
nums[i] = -nums[i];
}
for (let i = 0; i < len; i++) {
sum += nums[i];
}
console.log(nums);
console.log(sum);//26
很好的完成了!🎉
*/
//其次是k值在完成对负值的取反后,仍有多余次数,这个时候,只要再排序一次,把剩余次数全都用掉就好!
//let k = 6;
// console.log(nums);
for (let i = 0; i < len; i++) {
if (nums[i] < 0 && k > 0) {
nums[i] = -nums[i];
k--;
}
}
// console.log(k);
nums.sort(sortNumber);
if (k > 0) {
for (let i = 0; i < k; i++) {
nums[0] = -nums[0];
}
}
for (let i = 0; i < len; i++) {
sum += nums[i];
}
// console.log(nums);
// console.log(sum);
return sum;
};
//, k
largestSumAfterKNegations(nums, k);//这里测试的时候自己赋值就好
虽然只是简单题但是按照自己思路做出来了还是很高兴!