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

123 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

题目描述

给你一个整数数组 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]

思路分析

根据题意可知,我们需要将一个已知数组改变,数组所有元素相加之和就可能的大;这个数组是一个整数数组,可能有负数、零、正数;若要取最大之和,只能改变其最小的值。

  • 若是数组中有负数,优先将最小的负数转换成正数,那么数组之和将取到两倍原先负数的数值。
  • 若是数组中最小值是零,则只需要不停的转换0即可,直至k值等于0,这样虽不会增加数值,但会保持此数值是最大的数值。
  • 若是数组中最小的值大于零,则只需要改变最小值即可,这样可以做到损失最小化。 将数组从小到大进行排序,然后按照上面的条件进行转化即可。

AC代码

let arr = [1,2,3,-5,-6]
function largestSumAfterKNegations(arr, k) {
  arr.sort((a, b) => {return a - b});
  let i=0,leng = arr.length;
  while(i<leng, k>0) {
    // 如果当前遍历项小于0,则取反
    if(arr[i] < 0) {
      arr[i] = -arr[i];
      i++;
      k--
    }else{
      //如果当前遍历项是正数,判断与前一项的大小
      let index = arr[i] > arr[i - 1] ? i - 1 : i;
      arr[index] = k % 2 == 0 ? arr[index] : -arr[index];
      k = 0;
    }
  };
  let sum = arr.reduce((a, b) => { return a + b });
  console.log(sum);
}
largestSumAfterKNegations(arr, 2)

总结