消去思路-把已经过去的彻底抹除掉

95 阅读1分钟

有时候,会有一种变量是消费品,一旦使用便毫无意义,这时候就要考虑把他们忘掉,使用过后丢弃掉,具体的方法——减法。

题目:

给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:

选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。

以这种方式修改数组后,返回数组 可能的最大和 。

示例 1: 输入:nums = [4,2,3], k = 1 输出:5 解释:选择下标 1 ,nums 变为 [4,-2,3] 。

我的思路是区分k和负数的个数,然后再分情况讨论: 先对数组进行排序

  1. 当负数个数n>k时,直接反转绝对值最大的负数得到最大和;
  2. 当n<k时,反转所有的负数,然后根据剩余的k的值进行反转,偶数不动,奇数则选择排序中绝对值最小的负数和最小的正数之一进行反转,达到减去值为最小。 具体代码:
class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        int con=0;
        int  temp=0;
 for(int j=0;j<nums.length-1;j++)
            {for(int i=0;i<nums.length-j-1;i++)
                {if(nums[i]>nums[i+1])
                    {
                    temp=nums[i];
                    nums[i]=nums[i+1];
                    nums[i+1]=temp;
                    }
                }
            }
        

        for(int j=0;j<nums.length-1;j++){
             if (nums[j] < 0) {
             con++;
             }
        }
        int sum3 = 0;
        int sum1 = 0;
        int sum2 = 0;
        int sum4 = 0;
    if (k > con) {
                    for (int i = 0; i < con; i++) {
                        sum1 = nums[i] + sum1;
                    }
                    if ((k - con) % 2 == 0) {
                        for (int j = con + 1; j < nums.length; j++) {
                            sum2 = nums[j] + sum2;
                        }
                        sum3 = sum2 - sum1 + nums[con];
                    } else {
                        if(con>0&&nums[con]>Math.abs(nums[con-1])){
                            for (int j = con-1; j < nums.length; j++) {
                                sum2 = nums[j] + sum2;
                            }
                            sum3=sum2-sum1+nums[con-1];
                        }
                        else
                        {
                            for (int j = con+1; j < nums.length; j++) {
                                sum2 = nums[j] + sum2;
                            }
                            sum3 = sum2 - sum1 - nums[con];
                        }


                    }

                }
        if (k==con){
            for (int i = 0; i < con; i++) {
                sum1 = nums[i] + sum1;
            }
            for (int j = con; j < nums.length; j++) {
                sum2 = nums[j] + sum2;
            }
            sum3=sum2-sum1;
        } 
        if (k<con) {
            for (int i = 0; i < k; i++) {
                sum1 = sum1 + nums[i];
            }
            for (int j = k; j < nums.length; j++) {
                sum2 = sum2 + nums[j];
            }
            sum3 = sum2 - sum1;
        }
        return sum3;
    }
}

但实际上,还有更好的思路: 那就是做减法 把k当作消耗品,每次使用减去一个,对应数组中的负数,每次使用,反转一个负数,没有负数则不用翻转。 再次排序或者记录最小正数后,多出来的根据奇偶对最小的数进行处理。

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        // 排序,把可能有的负数排到前面
        Arrays.sort(nums);
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            // 贪心:如果是负数,而k还有盈余,就把负数反过来
            if (nums[i] < 0 && k > 0) {
                nums[i] = -1 * nums[i];
                k--;
            }
            sum += nums[i];
        }
        Arrays.sort(nums);
        // 如果k没剩,那说明能转的负数都转正了,已经是最大和,返回sum
        // 如果k有剩,说明负数已经全部转正,所以如果k还剩偶数个就自己抵消掉,不用删减,如果k还剩奇数个就减掉2倍最小正数。
        return sum - (k % 2 == 0 ? 0 : 2 * nums[0]); 
    }
}