LeetCode.1005-K次取負(fù)數(shù)組和最大(Maximize Sum Of Array After K Negations)

這是悅樂(lè)書(shū)的第376次更新,第403篇原創(chuàng)

01 看題和準(zhǔn)備

今天介紹的是LeetCode算法題中Easy級(jí)別的第237題(順位題號(hào)是1005)。給定一個(gè)整數(shù)數(shù)組A,我們必須按以下方式修改數(shù)組:我們選擇一個(gè)i并用-A[i]替換A[i],重復(fù)這個(gè)過(guò)程K次。(我們可以多次選擇相同的索引。)
以這種方式修改后,返回?cái)?shù)組可能的最大總和。例如:

輸入:A = [4,2,3], K = 1
輸出:5
說(shuō)明:選擇索引(1,),A變?yōu)?code>[4,-2,3]。

輸入:A = [3,-1,0,2], K = 3
輸出:6
說(shuō)明:選擇索引(1, 2, 2),A變?yōu)?code>[3,1,0,2]。

輸入:A = [2,-3,-1,5,-4], K = 2
輸出:13
說(shuō)明:選擇索引(1, 4),A變?yōu)?code>[2,3,-1,5,4]。

注意

  • 1 <= A.length <= 10000

  • 1 <= K <= 10000

  • -100 <= A[i] <= 100

02 第一種解法

題目的意思是將A中的數(shù)進(jìn)行取反(正變負(fù),負(fù)變正)K次,可以重復(fù)對(duì)一個(gè)元素取反,最后求A中元素總和的最大值。取反可以分為兩種情況:

當(dāng)A中都是正數(shù)的時(shí)候,比如{1,2,4,6},如果K是偶數(shù),那么可以不用進(jìn)行取反操作,因?yàn)樨?fù)負(fù)得正;如果K是奇數(shù),則只需要對(duì)最小的數(shù)取反一次即可。

當(dāng)A中有正數(shù)也有負(fù)數(shù)的時(shí)候,比如{-4,-3,-1,2,5},此時(shí)對(duì)負(fù)數(shù)元素進(jìn)行取反操作,直到當(dāng)前元素大于0或者K次轉(zhuǎn)換已用完,此時(shí)針對(duì)K中剩余的轉(zhuǎn)換次數(shù),又可以細(xì)分為兩種情況:

(1)K中剩余的轉(zhuǎn)換次數(shù)為偶數(shù),即A中元素全是正數(shù),依據(jù)負(fù)負(fù)得正,不用再進(jìn)行額外的轉(zhuǎn)換了。

(2)K中剩余的轉(zhuǎn)換次數(shù)為奇數(shù),即還需要再將某個(gè)元素轉(zhuǎn)換一次,而為了元素總和最大,需要比較當(dāng)前元素(正數(shù))和前一個(gè)元素(負(fù)數(shù))的絕對(duì)值大小,對(duì)較小的元素進(jìn)行取反。

最后使用一個(gè)for循環(huán),計(jì)算A中所有元素總和。

public int largestSumAfterKNegations(int[] A, int K) {
    int sum = 0;
    Arrays.sort(A);
    if (A[0] >= 0) {
        if (K%2 != 0) {
            A[0] = -A[0];
        }
    } else {
        int i = 0;
        while (A[i] <= 0 && K > 0) {
            A[i] = -A[i];
            i++;
            K--;
        }
        // K中剩余有轉(zhuǎn)換次數(shù)且為奇數(shù)
        if (K > 0 && K%2 != 0) {
            // 取較小的元素進(jìn)行取反
            if (Math.abs(A[i]) < Math.abs(A[i-1])) {
                A[i] = -A[i];
            } else {
                A[i-1] = -A[i-1];
            }
        }
    }
    // 求和
    for (int num : A) {
        sum += num;
    }
    return sum;
}


03 第二種解法

思路和第一種解法類似,只是在處理K中剩余的轉(zhuǎn)換次數(shù)為奇數(shù)這個(gè)問(wèn)題上做了下優(yōu)化,在第一種解法中,我們是比較最后一次轉(zhuǎn)換的負(fù)數(shù)和它前一個(gè)正數(shù)的大小,換種角度理解,這兩個(gè)數(shù)已經(jīng)處于所有元素中的底部了,就像一個(gè)U型曲線的底一樣,而為了元素總和最大,需要將較小的值取反,即找出所有元素中的最小值即可。

先對(duì)A排序,利用循環(huán),將前面的負(fù)數(shù)進(jìn)行轉(zhuǎn)換,順便計(jì)算元素總和并找出最小元素,如果A中負(fù)數(shù)已全部轉(zhuǎn)換完成(A中已不包含負(fù)數(shù)),且K中還有剩余的轉(zhuǎn)換次數(shù),并且剩余的轉(zhuǎn)換次數(shù)為奇數(shù),則將最小的正數(shù)減去兩次,因?yàn)?code>sum是全部元素的和,且全部元素都是正數(shù),對(duì)最小的元素取反后變?yōu)樨?fù)數(shù),則sum需要減兩次最小元素。例如{1,2,3}的和為6,對(duì)1取反后變?yōu)?code>{-1,2,3},其和為4。

public int largestSumAfterKNegations2(int[] A, int K) {
    Arrays.sort(A);
    int sum = 0, min = Integer.MAX_VALUE;
    for (int num : A) {
        if (num <= 0 && K > 0) {
            num = -num;
            K--;
        }
        sum += num;
        min = Math.min(min, num);
    }
    // K中有剩余轉(zhuǎn)換次數(shù)且為奇數(shù)
    if (K > 0 && K%2 != 0) {
        // 減去2次最小值
        sum -= min*2;
    }
    return sum;
}


04 小結(jié)

算法專題目前已連續(xù)日更超過(guò)七個(gè)月,算法題文章242+篇,公眾號(hào)對(duì)話框回復(fù)【數(shù)據(jù)結(jié)構(gòu)與算法】、【算法】、【數(shù)據(jù)結(jié)構(gòu)】中的任一關(guān)鍵詞,獲取系列文章合集。

以上就是全部?jī)?nèi)容,如果大家有什么好的解法思路、建議或者其他問(wèn)題,可以下方留言交流,點(diǎn)贊、留言、轉(zhuǎn)發(fā)就是對(duì)我最大的回報(bào)和支持!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容