[LeetCode] 1005. Maximize Sum Of Array After K Negations K次取反后最大化的數組和



Given an array A of integers, we must modify the array in the following way: we choose an i and replace A[i] with -A[i], and we repeat this process K times in total.  (We may choose the same index i multiple times.)

Return the largest possible sum of the array after modifying it in this way.

Example 1:

Input: A = [4,2,3], K = 1
Output: 5
Explanation: Choose indices (1,) and A becomes [4,-2,3].

Example 2:

Input: A = [3,-1,0,2], K = 3
Output: 6
Explanation: Choose indices (1, 2, 2) and A becomes [3,1,0,2].

Example 3:

Input: A = [2,-3,-1,5,-4], K = 2
Output: 13 Explanation: Choose indices (1, 4) and A becomes [2,3,-1,5,4].

Note:

  1. 1 <= A.length <= 10000
  2. 1 <= K <= 10000
  3. -100 <= A[i] <= 100

這道題給了一個整數數組,可能有正有負,然后給了一個正整數K,說是可以進行K次操作,每次操作是可以將任意位置的上的數字翻轉成其的相反數,即正數變負數,或者負數變正數,並且同一個位置上的數字可以進行多次變換,現在問經過K次變換后,返回最大的數組之和。首先來想,怎么使得數組和最大,肯定是正數越多越好,如果數組中有負數,肯定是要將其變為正數,此時數組中負數的個數和K之間的大小關系並不確定,所以需要分情況來討論。當然最簡單的情況就是負數的個數正好等於K,這樣只要將所有的負數都變成正數,就可以了。若負數的個數大於K,則肯定是選最小的K個,也就是絕對值最大的K個,這樣翻轉后和才能最大。若負數個數小於K,此時都翻轉成了正數,但是K值還沒用完,還是要翻轉,此時要分K的奇偶來討論,由於同一個位置可以多次翻轉,若K是偶數,則每次翻轉后都可以翻回去,沒有任何影響,而若K是奇數,則必定會有一個非負數會被翻轉,那肯定希望翻轉的是最小的非負數,從而對結果影響最小。分析到這,基本上整個解題思路就有了,使用一個優先隊列來記錄所有的負數的絕對值,再用一個變量 mn 來記錄數組中絕對值最小的數字,遍歷數組,若遇到負數,則將其對應的正數排入優先隊列,然后每次將這個數字加入結果 res,並且更新絕對值最小的數字。之后進行遍歷,遍歷的次數是負數的個數和K之間的較小值,每次取出絕對值最大的負數,將其絕對值乘以2並加入到結果 res 中。循環結束后,K的值可能或奇或偶,當K是偶數的時候(包括0),直接返回 res,若是奇數的話,要減去 mn 的2倍,這是數組中絕對值最小的數,參見代碼如下:


解法一:

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& A, int K) {
        int res = 0, n = A.size(), mn = INT_MAX;
        priority_queue<int> q;
        for (int num : A) {
            if (num < 0) q.push(-num);
            res += num;
            mn = min(mn, abs(num));
        }
        while (!q.empty() && K > 0) {
            res += q.top() * 2; q.pop();
            --K;
        }
        return res - (K % 2) * 2 * mn;
    }
};

我們也可以不用優先隊列,而是先給數組排個序,這樣所有的負數都在數組的前面了,然后此時將前K個負數翻轉成正數,注意只是翻轉負數,若負數的個數小於K,也不會翻轉多余的正數。然后此時遍歷數組,求數組之后,並且求此時數組中最小的數字,此時K還是有奇偶兩種情況,當K是偶數的時候(包括0),直接返回數組之和,若是奇數的時候,此時說明數組中的負數已經全部翻轉為了正數,那么最小的數也就是絕對值最小的數,減去其的2倍即可,參見代碼如下:


解法二:

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& A, int K) {
        int res = 0, n = A.size(), mn = INT_MAX;
        sort(A.begin(), A.end());
        for (int i = 0; i < n && K > 0 && A[i] < 0; ++i, --K) {
            A[i] = -A[i];
        }
        for (int num : A) {
            res += num;
            mn = min(mn, num);
        }
        return res - (K % 2) * 2 * mn;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1005


參考資料:

https://leetcode.com/problems/maximize-sum-of-array-after-k-negations/

https://leetcode.com/problems/maximize-sum-of-array-after-k-negations/discuss/252254/JavaC%2B%2BPython-Sort

https://leetcode.com/problems/maximize-sum-of-array-after-k-negations/discuss/252228/A-very-simple-java-solution


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM