贪心2:K 次取反后最大化的数组和

Posted 纵横千里,捭阖四方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心2:K 次取反后最大化的数组和相关的知识,希望对你有一定的参考价值。

我们说贪心算法很多解题思路是我们先 看出来了,然后只是用代码实现而已,这个题就很典型:

LeetCode1005,K次取反后最大化的数组和,给你一个整数数组 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次不断的取反。例如第一个例子是4,2,3,我们只反转一次,很显然反转2为-2,则结果为4+3-2=5最大,如果反转4或者3都会比5小,所以输出5。

而对于第二个3,-1,0,2,反转3次,很显然我们可以看到将-1转成正的,剩下的就是来回取反0,最大为6。当然也可以将-1取反3次得到1。

最后一个2,-3,-1,5,-4,有三个负数,而K=2只能取反两次,所以我们自然要选择最小的两个负数-3和-4,这样序列就变成了2,3,-1,5,4结果为13,最大。

很显然上面这个过程就是小学生也知道的方法。如果告诉你是个贪心问题,反而会吓跑一大波人,我们这里只是用贪心来包装了一下而已。

贪心的思路是局部最优:让绝对值大的负数变为正数,当前数值达到最大。整体最优:整个数组和达到最大。局部最优可以推出全局最优。

那么如果将负数都转变为正数了,K依然大于0,此时的问题是一个有序正整数序列,如何转变K次正负,让数组和达到最大。此时只找数值最小的正整数进行反转(局部最优),当前数值可以达到最大(全局最优)。

如果要变成能用代码解决的问题,大致有这么几个步骤:

  • 1带着正负号,将数组小到大排序
  • 2从前向后遍历,遇到负数将其变为正数,同时K--
  • 3如果负数没有了,K还大于0,那么反复反转绝对值最小的元素,将K用完
  • 4求和

 但是这么做的话,当负数都转完了,K还不是0,接下来的处理有点麻烦,我们可以按照绝对值进行排序,然后,再从后往前遍历,遇到负数反转,再到正数跳过,当然,这里我们可以边遍历边累加,最后,如果 k 还有剩余且为奇数,只要减去第一个数的绝对值的两倍即可。

class Solution 
    public int largestSumAfterKNegations(int[] nums, int k) 
        List<Integer> list = new ArrayList<>();
        for (int num : nums) 
            list.add(num);
        

        list.sort((a, b) -> Math.abs(a) - Math.abs(b));

        int ans = 0; 
        for (int i = list.size() - 1; i >= 0; i--) 
            if (k > 0 && list.get(i) < 0) 
                ans += -list.get(i);
                k--;
             else 
                ans += list.get(i);
            
        

        if (k % 2 != 0) 
            ans -= 2 * Math.abs(list.get(0));
        

        return ans;
    

这个题从不同的角度考虑至少有七八种方法能解决 ,感兴趣的小伙伴可以研究一下。

以上是关于贪心2:K 次取反后最大化的数组和的主要内容,如果未能解决你的问题,请参考以下文章

贪心算法:K次取反后最大化的数组和

LeetCode1005 K次取反后最大化的数组和(贪心+Java简单排序)

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

leetcode每日一题:1005. K 次取反后最大化的数组和

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

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