leetcode394,Leetcode OJ: Maximun Subarray

 2023-11-18 阅读 28 评论 0

摘要:Maximum Subarray Find the contiguous subarray within an array (containing at least one number) which has the largest sum. For example, given the array?[?2,1,?3,4,?1,2,1,?5,4],the contiguous subarray?[4,?1,2,1]?has the largest sum =?6. More practice:

Maximum Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array?[?2,1,?3,4,?1,2,1,?5,4],
the contiguous subarray?[4,?1,2,1]?has the largest sum =?6.

More practice:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

求子串最大和,第一次看到這題是在sogou的筆試,當時手寫代碼,用了動態規劃,以為就OK,誰知道在LeetCode上一敲各種bug。。

不過,總的思想是沒有錯的,只是要注意的點比較多,雖然不是最優的解法,但也陳述一下吧。

leetcode394,LZ先把問題想了想,求子串和最大,那什么是子串?拿以上數組為例,我們把子串的兩邊劃出來。

?[?2,1,?3, | 4,?1,2,1, |?5,4]

紅豎杠間是我們要最大和的子串,那么就是要左右兩側的子串和最小,那么就是兩側的和都分別最小則總和最小,即中間的子串即為最大。
以上說的是中心思想,但這里還有好多的情況要討論。
當紅線重合時,那么就是沒有子串,則需要其中一條紅線左移,或者右移一格。
當只有一條紅線時,即只考慮左側子串,或右側子串時,也要獨立考慮。
提交了N次才通過的代碼:
 1 class Solution {
 2 public:
 3     int maxSubArray(int A[], int n) {
 4         if (n == 1)
 5             return A[0];
 6         vector<int> fsum(n-1, 0), bsum(n-1, 0);
 7         vector<bool> fflag(n-1, false), bflag(n-1, false);
 8         int tsum = A[0];
 9         fsum[0] = A[0];
10         fflag[0] = true;
11         
12         for (int i = 1; i < n-1; ++i) {
13             tsum += A[i];
14             if (tsum < fsum[i-1]) {
15                 fsum[i] = tsum;
16                 fflag[i] = true;
17             } else {
18                 fsum[i] = fsum[i-1];
19             }
20         }
21         tsum = A[n-1];
22         bsum[n-2] = A[n-1];
23         bflag[n-2] = true;
24         for (int i = n-2; i > 0; --i) {
25             tsum += A[i];
26             if (tsum < bsum[i]) {
27                 bsum[i-1] = tsum;
28                 bflag[i-1] = true;
29             } else {
30                 bsum[i-1] = bsum[i];
31             }
32         }
33         tsum += A[0];
34         int ret = tsum;
35         for (int i = 0; i < n-1; ++i) {
36             int tmp = tsum - min(fsum[i], bsum[i]);  // 只考慮左側或右側
37             if (!fflag[i] || !bflag[i]) { // 分隔線不重合
38                 if (tmp < tsum - fsum[i] - bsum[i])
39                     tmp = tsum - fsum[i] - bsum[i];
40             } else {  // 分隔線重合
41                 if (i > 0 && tmp < tsum - fsum[i-1] - bsum[i]) {
42                     tmp = tsum - fsum[i-1] - bsum[i];
43                 }
44                 if (i < n-2 && tmp < tsum - fsum[i] - bsum[i+1]) {
45                     tmp = tsum - fsum[i] - bsum[i+1];
46                 }
47             }
48             if (tmp > ret) {
49                 ret = tmp;
50             }
51         }
52         return ret;
53     }
54 };

成功拖低了平均水平,然后實在想知道有沒更好的方法,上網一搜果斷有的,找到了傳說中的Kadane算法(自行百度吧),代碼只有幾行(傷透了我的心。。),這里直接貼一下吧:

 1 class Solution {
 2 public:
 3     int maxSubArray(int A[], int n) {
 4         int ans = 0, maxn = INT_MIN;  
 5         for(int i = 0; i < n; i++){  
 6             if(ans < 0) ans = 0;  
 7             ans += A[i];  
 8             maxn = max(maxn, ans);   
 9         }  
10         return maxn;  
11     }
12 };

然后LZ蛋疼地去看下運行時間,發現居然比我的方法慢?不能理解。多提交了幾次,也是這樣,于是想了想,發現這代碼里面用了max函數,而且每次都要重要賦值,其實可以先判斷再賦值。LZ加了個判斷再賦值,然后提交,果斷快了,嗯,這是小插曲,大家可以不用管LZ自娛自樂。

然后就是分治的思路了,這個其實我也不太懂,不過看別人的代碼確實還是學了不少的,直接轉別人的代碼吧(以上Kadane算法也是別人的代碼)。

三個狀態:begin, end, mid=(begin+end)/2

leetcode121。1. 在A[begin..mid-1]間

2. 在A[mid+1..end]間

3. 包含A[mid]的區間

 1 class Solution {
 2 public:
 3     int divide(int A[], int begin, int end) {
 4         if (begin == end) return A[begin];
 5         if (begin + 1 == end)
 6             return max(max(A[begin], A[end]), A[begin] + A[end]);
 7         int mid = begin + (end - begin) /2;
 8         int lmax = divide(A, begin, mid - 1);
 9         int rmax = divide(A, mid + 1, end);
10         int mmax = A[mid];
11         int tmp = A[mid];
12         for (int i = mid-1; i >= begin; --i) {
13             tmp += A[i];
14             if (tmp > mmax)
15                 mmax = tmp;
16         }
17         tmp = mmax;
18         for (int i = mid+1; i <= end; ++i) {
19             tmp += A[i];
20             if (tmp > mmax) {
21                 mmax = tmp;
22             }
23         }
24         return max(max(lmax, rmax), mmax);
25     }
26     int maxSubArray(int A[], int n) {
27         return divide(A, 0, n-1);
28     }
29 };

代碼轉自http://blog.csdn.net/xshengh/article/details/12708291

轉載于:https://www.cnblogs.com/flowerkzj/p/3632513.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/175375.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息