K次取反后最大化的数组和
题目描述 :
给定一个整数数组
A
,我们只能用以下方法修改该数组:我们选择某个索引i
并将A[i]
替换为-A[i]
,然后总共重复这个过程K
次。(我们可以多次选择同一个索引i
。)以这种方式修改数组后,返回数组可能的最大和。
示例 :
思路 :
大家仔细观察示例的输入后可以发现,我们需要从最小的数开始反转。如果数组里有负数,首先需要先将负数进行反转,每次反转最小的负数。如果数组里都是正数,这是需要分三种情况:
- 如果
K
为偶数,每次反转数组里最小的数,最后得到的数组保持不变(即与原数组相同)。所以当K
为偶数时,直接求所有元素的和 - 如果
K
为奇数,反转后得到的结果即为将数组最小值取反,其它值不变。所以此时求和为-A[0] + A[1] + …… + A[n]
- 如果
K
为0,直接求和
代码 (三种解法):
-
n次排序(最短代码)
每次将最小的元素取反,要用进行
K
次排序,用时较长。class Solution { public: int largestSumAfterKNegations(vector<int>& A, int K) { while (K--) { sort(A.begin(), A.end()); A[0] = -A[0]; } int sum = 0; for (int a: A) sum += a; return sum; } };
-
两次排序
第一次排序先将数组里的负数反转,第二次排序时处理正数的情况。
class Solution { public: int largestSumAfterKNegations(vector<int>& A, int K) { sort(A.begin(), A.end()); for (int i = 0; A[i] < 0 && K > 0; i++, K--) { A[i] = -A[i]; } sort(A.begin(), A.end()); int sum = 0; for (int i = 1; i < A.size(); i++) { sum += A[i]; } if (K > 0 && K % 2 != 0) { sum = sum - A[0]; } else { sum += A[0]; } return sum; } };
-
一次排序
将数组里的数按照绝对值 进行排序,排序后首先反转数组里的负数,然后根据
K
值求和。class Solution { public: int largestSumAfterKNegations(vector<int>& A, int K) { int res = 0; sort(A.begin(), A.end(), [](int a, int b)->bool {return abs(a) > abs(b);}); //匿名函数 for (int i = 0; i < A.size(); i++) { if (A[i] < 0 && K > 0) { A[i] *= -1; K--; } } if (K > 0 && K % 2 != 0) A[A.size() -1] *= -1; for (int a : A) res += a; return res; } };