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 <= A.length <= 10000
1 <= K <= 10000
-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/