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

该博客讨论了一种算法问题,即在给定数组和修改次数k的情况下,如何通过取反数组中的元素来最大化数组的和。解决策略是首先对数组进行升序排序,然后从最小的负数开始取反,直到所有负数变为正数或用完k次修改。如果k还有余数,且为奇数,则取反当前最小的数。举例说明了该策略的正确性,并提供了相应的Java代码实现。

题目来源:https://leetcode-cn.com/problems/maximize-sum-of-array-after-k-negations/

大致题意:
给定一个数组 nums 和修改次数 k,每次修改都将数组的某一位取相反数,求出 k 次修改后数组可能的最大元素和

思路

先排序,然后从后往前(从最小的数开始)一个个取反

排序
  1. 先将数组升序排序
  2. 从后往前(从最小的数开始)把负数一个个取反,直到所有负数都为正数或者已经修改 k 次
  3. 此时判断修改次数是否用完,若未用完,那么判断 k 是否为奇数,为奇数代表还需要取反一个当前的最小数(最小数就在上一轮最后遍历位置的数和其前一个数之间);为偶数就不用管了(负负得正)。而若修改次数已经用完,也不用管了(已经尽可能的把最小的负数都变正了)

为什么最小数就在上一轮最后遍历位置的数和其前一个数之间?因为此时已经取反完毕,遍历到第一个非负数,而这个正数就是取反前的最小非负数,而前一个位置就是取反前的最大负数,也就是负数取反后的最小值,那么当前数组的最小值一定从它俩之间选出
给两个例子:
-6, -5, -1, 2, 3 修改次数为 4 那么最后就是将取反后的 1 再取反,因为 1 小于其右侧的 2

-6, -5, -2, 1, 3 修改次数为 4 那么最后就是将取反前最小的非负数 1 取反,因为 1 小于其左侧的 2(-2 取反的结果)

代码:

public int largestSumAfterKNegations(int[] nums, int k) {
        Arrays.sort(nums);  // 升序排序
        int idx = 0;
        int n = nums.length;
        // 取反
        // 注意边界
        while (idx < n && nums[idx] < 0 && k > 0) {
            nums[idx] = -nums[idx];
            idx++;
            k--;
        }
        // 如果遍历到最后一个位置,修改次数还未用完,为防止越界需要 -1
        if (idx == n) {
            idx--;
        }
        // 当修改次数未用完,且剩余次数为奇数
        if (k > 0 && k % 2 == 1) {
            // 将目前的最小值取反
            if (idx > 0 && nums[idx] > nums[idx - 1]) {
                nums[idx - 1] = -nums[idx - 1];
            } else {
                nums[idx] = -nums[idx];
            }
        }
        return Arrays.stream(nums).sum();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三更鬼

谢谢老板!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值