「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」
题目
给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)
以这种方式修改数组后,返回数组可能的最大和。
示例 1:
- 输入:A = [4,2,3], K = 1
- 输出:5
- 解释:选择索引 (1,) ,然后 A 变为 [4,-2,3]。
示例 2:
- 输入:A = [3,-1,0,2], K = 3
- 输出:6
- 解释:选择索引 (1, 2, 2) ,然后 A 变为 [3,1,0,2]。
示例 3:
- 输入:A = [2,-3,-1,5,-4], K = 2
- 输出:13
- 解释:选择索引 (1, 4) ,然后 A 变为 [2,3,-1,5,4]。
提示:
- 1 <= A.length <= 10000
- 1 <= K <= 10000
- -100 <= A[i] <= 100
解法
贪心的思路,局部最优:让绝对值大的负数变为正数,当前数值达到最大,整体最优:整个数组和达到最大。
局部最优可以推出全局最优。
那么如果将负数都转变为正数了,K依然大于0,此时的问题是一个有序正整数序列,如何转变K次正负,让 数组和 达到最大。
那么又是一个贪心:局部最优:只找数值最小的正整数进行反转,当前数值可以达到最大(例如正整数数组{5, 3, 1},反转1 得到-1 比 反转5得到的-5 大多了),全局最优:整个 数组和 达到最大。
解题思路:
1.从小到大排序 2. 遍历nums,当nums[i]为负数切k>0时,将nums[i]反转同时k-- 3. 当所有负数反转完成,判断若k>0且k为奇数,再次排序nums[i](题目允许反转同一数值,所以只要保证最小的在第一位重复反转最小即可,因此k为偶数无需考虑) 4.求和
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var largestSumAfterKNegations = function(nums, k) {
nums.sort((a,b)=>a-b)
let num = 0
for(let i=0;i<nums.length;i++){
if(nums[i]<0&&k>0){
nums[i]=nums[i] * -1
k--
}
}
if(k>0&&k%2===1){
nums.sort((a,b)=>a-b)
nums[0]=nums[0] * -1
}
nums.map(item=>{
num+=item
})
return num
};