贪心 1005.K次取反后最大化的数组和

1005.K次取反后最大化的数组和

题目:

给定一个数组和k,k是需要反转某个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。

要求返回完成反转后能返回的数组最大总和

(可以重复反转一个元素)

示例 1:

  • 输入:A = [4,2,3], K = 1
  • 输出:5
  • 解释:选择索引 (1,) ,然后 A 变为 [4,-2,3]。

示例 2:

  • 输入:A = [3,-1,0,2], K = 3
  • 输出:6
  • 解释:选择索引 (1, 2, 2) ,然后 A 变为 [3,1,0,2]。

示例 3:

  • 输入:A = [2,-3,-1,5,-4], K = 2
  • 输出:13
  • 解释:选择索引 (1, 4) ,然后 A 变为 [2,3,-1,5,4]。

贪心思路:

贪心一:

当数组元素有负数的反转选择。

局部:利用K的次数,把数组中绝对值大的负数优先转成正的,增大总和。

全局:每一次都把绝对值大的负数转成正数,对全局增加总和的效力最大。

贪心二:

数组元素都为正时的反转选择。

局部:如果数都转成正数了,还留下来反转次数没用,那就需要用K转化绝对值最小的正数了,这样对总和影响最小,而且因为可以反复反转同一个元素,所以如果是留下来的次数是偶数可以,转成正的又转过来所以,直接清空次数,是奇数,就转一次最小的,这样影响最小

全局:装完负数后,剩下来的L如果是奇数只反转最小的,偶数直接清空,这样总和增加最多,消耗最小。

解题步骤:

  • 第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
  • 第二步:从前向后遍历,遇到负数将其变为正数,同时K--
  • 第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
  • 第四步:求和 
class Solution {
static bool cmp(int a, int b) {
    return abs(a) > abs(b);
}
public:
    int largestSumAfterKNegations(vector& A, int K) {
        sort(A.begin(), A.end(), cmp);       // 第一步
        for (int i = 0; i < A.size(); i++) { // 第二步
            if (A[i] < 0 && K > 0) {
                A[i] *= -1;
                K--;
            }
        }
        if (K % 2 == 1) A[A.size() - 1] *= -1; // 第三步
        int result = 0;
        for (int a : A) result += a;        // 第四步
        return result;//遍历A中的每一个元素a,都加到result上面
    }
};

你可能感兴趣的:(算法,数据结构)