專欄:50多種數(shù)據(jù)結(jié)構(gòu)徹底征服

專欄:50多種經(jīng)典圖論算法全部掌握

最近一網(wǎng)友收到一個offer,因為自己在洗澡沒有看到,結(jié)果過了40分鐘hr又把offer給撤回了,關(guān)鍵hr還把他的聯(lián)系方式給刪了,也沒辦法爭取了。

我對這種僅過了40分鐘就撤回offer的行為很是不能理解,說明他們也不是真的很缺人,如果真的缺人,也不會在乎那幾十分鐘,所以不去也挺好。

打開網(wǎng)易新聞 查看精彩圖片
打開網(wǎng)易新聞 查看精彩圖片
打開網(wǎng)易新聞 查看精彩圖片
打開網(wǎng)易新聞 查看精彩圖片

--------------下面是今天的算法題--------------

來看下今天的算法題,這題是LeetCode的第1186題:刪除一次得到子數(shù)組最大和,難度是中等。

給你一個整數(shù)數(shù)組,返回它的某個非空子數(shù)組(連續(xù)元素)在執(zhí)行一次可選的刪除操作后,所能得到的最大元素總和。換句話說,你可以從原數(shù)組中選出一個子數(shù)組,并可以決定要不要從中刪除一個元素(只能刪一次哦),(刪除后)子數(shù)組中至少應(yīng)當(dāng)有一個元素,然后該子數(shù)組(剩下)的元素總和是所有子數(shù)組之中最大的。

示例1:

輸入:arr = [1,-2,0,3] 輸出:4 解釋:我們可以選出 [1, -2, 0, 3],然后刪掉 -2,這樣得到 [1, 0, 3],和最大。

示例2:

輸入:arr = [1,-2,0,3] 輸出:4 解釋:我們可以選出 [1, -2, 0, 3],然后刪掉 -2,這樣得到 [1, 0, 3],和最大。

  • 1 <= arr.length <= 10^5

  • -10^4 <= arr[i] <= 10^4

問題分析

這題說的是從原數(shù)組中最多刪除一個元素,然后求最大連續(xù)子數(shù)組的和,實際上這是一道動態(tài)規(guī)劃的問題。

我們定義dp[i][0]表示沒有刪除任何元素且以arr[i]為結(jié)尾的最大連續(xù)子數(shù)組之和。dp[i][1]表示最多刪除一個元素且以arr[i]為結(jié)尾的最大連續(xù)子數(shù)組之和,刪除前以arr[i]為結(jié)尾的也算。最后保存最大值即可。

很明顯我們可以得出:

dp[i][0] = Math.max(dp[i - 1][0], 0) + arr[i];

dp[i][1] = Math.max(dp[i - 1][1] + arr[i], dp[i - 1][0]);

dp[i][0]表示沒有刪除任何元素,以它結(jié)尾的最大連續(xù)子數(shù)組之和是它自己arr[i]加上它前面的連續(xù)子數(shù)組之和,如果它前面的連續(xù)子數(shù)組之和為負(fù)數(shù),就不要加了 。

dp[i][1]表示最多刪除一個元素,也可能是之前就已經(jīng)刪除過,所以我們?nèi)p[i - 1][1] + arr[i],也可能是之前沒有刪除過,而是把當(dāng)前的元素arr[i]給刪除了,我們?nèi)?dp[i - 1][0],這兩種情況我們?nèi)?a class="keyword-search" >最大值即可。

動態(tài)規(guī)劃有了遞推公式就簡單了,我們在看下Base Case,第一個元素如果沒有刪除,則dp[0][0] = arr[0];如果刪除了,則dp[0][1] = 0。

JAVA:

public int maximumSum(int[] arr) {     int n = arr.length;     int[][] dp = new int[n][2];     dp[0][0] = arr[0];// 第一個元素沒有刪除     dp[0][1] = 0;// 第二個元素被刪除     int ans = arr[0];// 保存最大值。     for (int i = 1; i < arr.length; i++) {         dp[i][0] = Math.max(dp[i - 1][0], 0) + arr[i];         dp[i][1] = Math.max(dp[i - 1][1] + arr[i], dp[i - 1][0]);         ans = Math.max(ans, Math.max(dp[i][0], dp[i][1]));     }     return ans; }

C++:

public:     int maximumSum(vector

 &arr) {         int n = arr.size();         vector

 > dp(n, vector

 (2, 0));         dp[0][0] = arr[0];// 第一個元素沒有刪除         dp[0][1] = 0;// 第二個元素被刪除         int ans = arr[0];// 保存最大值。         for (int i = 1; i < n; i++) {             dp[i][0] = max(dp[i - 1][0], 0) + arr[i];             dp[i][1] = max(dp[i - 1][1] + arr[i], dp[i - 1][0]);             ans = max(ans, max(dp[i][0], dp[i][1]));         }         return ans;     }


筆者簡介

博哥,真名:王一博,畢業(yè)十多年, 作者,專注于 數(shù)據(jù)結(jié)構(gòu)和算法 的講解,在全球30多個算法網(wǎng)站中累計做題2000多道,在公眾號中寫算法題解800多題,對算法題有自己獨特的解題思路和解題技巧,喜歡的可以給個關(guān)注,也可以 下載我整理的1000多頁的PDF算法文檔 。