LeetCode1005.K次取反后最大化的数组和

134 阅读1分钟

「这是我参与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
};