数组精选题目三连(5)
子數組的最大累加和問題
輸入一個整形數組,求數組中連續的子數組使其和最大。比如,數組x
應該返回 x[2..6]的和187.
?
這四個代碼完成的功能都是求最大子數組(注意用詞準確,子數組連續,子序列可以不連續)。
1)
for(i = 1; i <= n; i++)scanf("%d", &num[i]); ans = num[1]; for(i = 1; i <= n; i++) {for(j = i; j <= n; j++) {s = 0;for(k = i; k <= j; k++)s += num[k];if(s > ans)ans = s;} }分別枚舉每一個子數組的起點和終點,也就是i和j,對于每一個起點和終點,對中間部分求和,也就是k循環。顯然有n個起點n個終點(去重減半,不影響復雜度),所以子數組數量為O(N^2),對于每個子數組,我們要遍歷一下求和,子數組長度1-n不等,遍歷一遍平均O(N),乘起來O(N^3).(注意可能產生時間更大的錯覺)。找出所有子數組中最大的即可。
2)
for(i = 1; i <= n; i++)scanf("%d", &num[i]); sum[0] = 0; for(i = 1; i <= n; i++) {sum[i] = num[i] + sum[i - 1]; } ans = num[1]; for(i = 1; i <= n; i++) {for(j = i; j <= n; j++) {s = sum[j] - sum[i - 1];if(s > ans) ans = s;} }預處理出每一個以第一個元素開始,第i個元素結尾的子數組和,還是枚舉每個起點終點,但是我們求和時直接減就可以了,不用遍歷。對于每個子數組,操作為O(1),子數組數量O(N^2),所以總時間O(N^2).
3)
int solve(int left, int right) {if(left == right)return num[left];mid = (left + right) / 2;lans = solve(left, mid);rans = solve(mid + 1, right);sum = 0, lmax = num[mid], rmax = num[mid + 1];for(i = mid; i >= left; i--) {sum += num[i];if(sum > lmax) lmax = sum;}sum = 0;for(i = mid + 1; i <= right; i++) {sum += num[i];if(sum > rmax) rmax = sum;}ans = lmax + rmax;if(lans > ans) ans = lans;if(rans > ans) ans = rans;return ans; }int main(void) {scanf("%d", &n);for(i = 1; i <= n; i++)scanf("%d", &num[i]);printf("%d\n", solve(1, n));return 0; }二分,求左右兩邊最大子數組,取最大。但是還有一種情況:包含斷點的那些子數組也要考慮,請思考那兩個那兩個循環為什么那么寫?最后邏輯為何正確?
4)動態規劃入門思想
沒有枚舉,num[i]的含義是以下標i結尾的所有子數組中最大的。
遍歷數組,對于第i個元素,它的所有子數組下標范圍有[1,i],[2,i].....[i-1,i],還有它自己,我們看i-1個元素,他的子數組為[1,i-1],[2,i-1].....[i-1]。請想num[i]的含義,我們求i結尾的,只要把i-1結尾的最大加上i就好了,當然如果i-1結尾最大子數組是負的,i結尾最大子數組就是它本身。
為什么O(N)?時間省在哪里了?我們省掉了許多沒必要的計算,計算i時,之前的數組和已經都計算過,樸素算法并沒有記錄下來,而是重復計算,造成時間浪費。算法優化的過程就是去掉重復計算的過程。
?
子矩陣的最大累加和問題
給一個矩陣,請找出一個矩陣中,和最大的子矩陣。
?
?
?
如果大家看懂了之前的講解,我給個提示:利用第二個代碼和第四個代碼思想的結合
?
?
解釋:
1???2??3???4
-1 -2??1???2
1???3???-2??1
-1??-2??-1??-3
如圖是前三行整體最大
怎么做呢?
先用第二個代碼的思想,我們進行預處理
每個數代表這一列到這個數位置截止,累加和。
1??2??3??4
0??0??4??6
1??3??2??7
0??1??1??4
然后,我們枚舉每一列的起點和終點分別為第0,1,2,3行
然后壓縮成一維來做
比如求1-3行的這個矩形,我們拿0和3行減一下就行了
0-1,1-2,1-3,4-4=-1,-1,-2,0就是1-3行壓縮后的結果
然后按一維dp來做就好
?
子數組的最大累乘積
題目:
給定一個double類型的數組arr,其中的元素可正、可負、可為0。返回子數組累乘的最大乘積。
思路:
假設以arr[i-1]結尾的數組最小累乘積為min,最大累乘積為max,那么以arr[i]結尾的數組的最大累乘積可能有三種情況。
- max*arr[i]//本身乘之前的最大累乘
- min*arr[i]//可能是負負得正變成最大的
- arr[i]//可能就是它本身,比如之前的max小于1
?
總結
以上是生活随笔為你收集整理的数组精选题目三连(5)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode172. 阶乘后的零 最
- 下一篇: 18暑期培训总结