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

Posted ZSYL

tags:

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

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

题目描述

题目来源:LeetCode1005

给定一个整数数组 A,我们只能用以下方法修改该数组:
我们选择某个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)
以这种方式修改数组后,返回数组可能的最大和。

算法分析

考虑贪心的最优策略:
我们必须经历 K 次取反操作,因此,为了使我们的数组和维持最大,我们可以将所有负数取反,若最后 K 还有剩余,可当前所有数已经为大于等于0,没有其他选择,则只能将 最小的数 取反剩余次数。

代码展示

桶排序

数值范围 -100~100,因此考虑创建数组大小 200,其中 0 代表-100,100代表 0,200代表100。
数值+100 映射到 0~200

class Solution {
     public int largestSumAfterKNegations(int[] A, int K) {
        int[] number = new int[201]; // -100 <= A[i] <= 100,这个范围的大小是201
        for (int t : A) {
            number[t + 100]++; // 将[-100,100]映射到[0,200]上
        }
        int i = 0;
        while (K > 0) {
            while (number[i] == 0) // 找到A[]中最小的数字
                i++;
            number[i]--; // 此数字个数-1
            number[200 - i]++; // 其相反数个数+1
            if (i > 100) { // 若原最小数索引>100,则新的最小数索引应为200-i.(索引即number[]数组的下标)
            	// 即原来最小值是正数,求反后变为负数,同时也是当前最小值
                i = 200 - i;
            }
            K--;
        }
        int sum = 0;
        for (int j = i; j <number.length ; j++) { // 遍历number[]求和
            sum += (j-100)*number[j]; // j-100是数字大小,number[j]是该数字出现次数.
        }
        return sum;
    }
}

贪心算法

  • 按照绝对值从大到小排序,注意要按照绝对值的大小
  • 从前向后遍历,遇到负数将其变为正数,同时 K–
  • 注意遍历同时求和
  • 如果 K 还大于0,那么反复转变数值最小的元素,将 K 用完
  • K是偶数次就不用管,奇数次的话只用减去一次最小值即可。
class Solution:
    def largestSumAfterKNegations(self, A: List[int], K: int) -> int:
        # 将整数按照绝对值排序,降序
        A = sorted(A, key=lambda a: abs(a), reverse=True)
        # 从前向后找如果遇到负数直接取反,K--
        ans = 0
        for i in range(len(A)):
            if A[i] < 0 and K > 0:
                A[i] = -A[i]
                K -= 1
            ans += A[i]
        # 如果最后剩余 K是奇数,只用将和-取最小的数的反
        # 偶数就不用管,两次取反和相当于 0
        if K % 2 == 1:
            ans -= 2 * A[len(A)-1]
        return ans     

感谢LeetCode大佬代码!
加油!

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

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

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

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

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

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

《LeetCode之每日一题》:226.K 次取反后最大化的数组和