Leetcode.1005. Maximized array sum after K negations - greedy + count sorting

Keywords: Algorithm data structure leetcode greedy algorithm

12.6 one question per day - maximum array sum after K inversions

Enter an array of integers and an integer k to modify the array as follows
1. Select a subscript i and replace num [i] with - num [i]
2. Repeat this process exactly k times. You can select the same subscript i multiple times.
When the array is modified in this way, the maximum possible sum of the array is returned.
(this time I'm still posting a blog link)

Input: nums = [4,2,3], k = 1
 Output: 5
 Explanation: select subscript 1, nums Become [4,-2,3] . 
Input: nums = [3,-1,0,2], k = 3
 Output: 6
 Input: nums = [2,-3,-1,5,-4], k = 2
 Output: 13
 Input: nums = 
[-2,5,0,2,-2],
k = 3
 Output: 11
 Of which:
1 <= nums.length <= 10000
-100 <= nums[i] <= 100
1 <= k <= 10000

Solution:

Method 1: quick sort + greedy

After sorting the array, if we want to maximize the sum of the array after reversing k times as much as possible, of course, we give priority to turning the negative number in the array into a positive number. At this time, the relationship between k and the number of negative numbers in the array will be involved.

  1. If k is greater than the number of negative numbers, we first turn all negative numbers into positive numbers, and then we judge whether the remaining k is even. If it is an even number, it is obvious that according to the nature of negation twice, we don't need to operate any more. We can directly accumulate the sum of the array. If it is an odd number, we just need to find the absolute value comparison between the smallest positive number and the largest negative number of the sorted array. Whoever has a small absolute value, we can turn him into a negative number according to the greedy idea.
  2. If k is less than the number of negative numbers, we can change as many negative numbers as we can.
public class Test {
    public static void main(String[] args) {
        int[] a = {3,-1,0,2};
        int[] b = {2,-3,-1,5,-4};
        int k1 = 3;
        int k2 = 4;
        System.out.println("And are:"+solution(a, k1));
    }

    public static int solution(int[] res,int k){
        int sum=0;
        int flag= 0;
        Arrays.sort(res);
        for(int i=0;i<res.length;i++){
            if(res[i]<0 && k>0){
                res[i] = -res[i];
                k--;
            }
            if (i-1>=0&&res[i-1] < 0 && res[i]>=0) {
                flag=i;
            }
            sum+=res[i];
        }
        if (k%2==0){
            return sum;
        }else{
            if(flag!=0) {
                return sum-2*Math.min(-res[flag-1],res[flag]);
            }else {
                return sum-2*res[0];
            }
        }
    }
}

Method 2: counting sorting + greed

Note the value range of num [i]. We can see that its range is small, so we can use the idea of counting and sorting to solve it at this time.
We can learn about it briefly through an article: Count sort.

  • After understanding the counting sorting, we can create a hash array as our mapping array and map the numbers in num into this array. Therefore, this hash array plays the role of sorting and storage. Then we traverse this hash array and follow the greedy idea of method 1. Here, we just use counting sorting instead of fast sorting.
class Test {
    public static void main(String[] args) {
        int[] a = {3,-1,0,2};
        int[] b = {2,-3,-1,5,-4};
        int k1 = 3;
        System.out.println("And are:"+largestSumAfterKNegations(a, k1));
    }

    public static int largestSumAfterKNegations(int[] nums, int k) {
        int[] hash = new int[201];
        for(int i=0;i<nums.length;i++){
            hash[nums[i]+100]++;
        }

        int sum = 0;
        int i = 0;
        while(k>0){
            while(hash[i]==0){ //There are no storage elements at this location
                i++;
            }
            if(i==100){  //The element is 0
                k--;
                continue;
            }
            else if(i<100){
                hash[i]--;  //Because of the inversion, the element at this position is missing
                hash[200-i]++;  //Add 1 element to the inverted position
                k--;
            }
            else{
                if(k%2==0){
                    break;
                }
                hash[i]--;
                hash[200-i]++;
                i=200-i;
                k--;
            }
        }

        for(i=0;i<hash.length;i++){
            sum+=hash[i]*(i-100);
        }

        return sum;
    }
}

Leetcode:

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        int[] hash = new int[201];
        for(int i=0;i<nums.length;i++){
            hash[nums[i]+100]++;
        }

        int sum = 0;
        int i = 0;
        while(k>0){
            while(hash[i]==0){
                i++;
            }
            if(i==100){
                k--;
                continue;
            }
            else if(i<100){
                hash[i]--;
                hash[200-i]++;
                k--;
            }
            else{
                if(k%2==0){
                    break;
                }
                hash[i]--;
                hash[200-i]++;
                k--;
            }
        }

        for(i=0;i<hash.length;i++){
            sum+=hash[i]*(i-100);
        }

        return sum;
    }
}

Posted by nicholasstephan on Mon, 06 Dec 2021 13:03:44 -0800