【貪心】C020_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.

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

Note:

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

二、題解

方法一:K 次排序

  • 如何高效的找到最小值的索引 i,然後將其變爲 -A[i]
  • 一個樸素的做法就是,每次取反之前對數組進行升序排列,排序後的第一個元素始終是最小的。

A.length 最大 10000,K 最大 10000,K×nlognK × nlogn 大概執行 108×410^8 × 4 次。勉強過…

public int largestSumAfterKNegations(int[] A, int K) {
    int sum = 0;
    while (K-- > 0) {
        Arrays.sort(A);
        A[0] = -A[0];
    }
    for (int n : A)
        sum += n;
    return sum;
}

複雜度分析

  • 時間複雜度:O(K×nlogn)O(K × nlogn)
  • 空間複雜度:O(1)O(1)

方法二:維護最小值下標

方法一的 K 次排序存在冗餘,因爲每一次排序後最小值可能還是自己,這種情況會使得下一次排序變得徒勞。我們可以這樣做:

  • 每次將最小值取反,然後判斷下一個數字是否比取反後的數字小。
    • 若是,則將 mini 指向下一個數字。
    • 否則,下一輪取反時,取反當前最小值 A[mini] 會使得總和最大。
public int largestSumAfterKNegations(int[] A, int K) {
    Arrays.sort(A);
    int mini = 0, N = A.length;
    while (K-- > 0) {
        A[mini] = -A[mini];
        if (mini + 1 < N && A[mini+1] < A[mini])
            mini = mini + 1;
    }
    int sum = 0;
    for (int n : A)
        sum += n;
    return sum;
}

複雜度分析

  • 時間複雜度:O(nlogn)O(nlogn)
  • 空間複雜度:O(1)O(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章