動態規劃問題系列---連續子陣列(二維)的最大和
題目1
一維陣列的連續子陣列的最大和
輸入一個整型陣列,數組裡有正數也有負數。陣列中一個或連續的多個整陣列成一個子陣列。求所有子陣列的和的最大值。要求時間負責度為O(n)。
分析
假如輸入陣列為{1,-2,3,10,-4,7,2,-5},我們嘗試從頭到尾累加其中的正數,初始化和為0,第一步加上1,此時和為1,第二步加上-2,此時和為-1,第三步加上3,此時我們發現-1+3=2,最大和2反而比3一個單獨的整數小,這是因為3加上了一個負數,發現這個規律以後我們就重新作出累加條件:如果當前和為負數,那麼就放棄前面的累加和,從陣列中的下一個數再開始計數。
實現
public class Num6 {
/**
* @param args
*/
public static void main(String[] args) {
int[] a={1,-2,3,10,-4,7,2,-5};
maxSum(a);
}
public static void maxSum(int[] a){
int maxSum=a[0];
int sum=a[0];
int start=0;
int begin=0,end=0;
for(int i=1 ;i<a.length;i++){
if(sum<0){
sum=a[i];
start=i;
}else{
sum+=a[i];
}
if(sum>maxSum){
maxSum=sum;
begin=start;
end=i;
}
}
System.out.println("maxSum=" +maxSum);
for(int i=begin;i<=end;i++){
System.out.print(a[i]+" ");
}
}
}
題目2
二維陣列的連續子陣列的最大和。
二維陣列的連續子陣列即為一個矩陣;
如下圖所示
設矩陣的坐上頂點為A(i,j), 右下頂點為 B(endi, endj). 在圖中即為 A(1,1), B(3,3)。我們可以用Rect(A,B)即 (1,1,3,3,)來表示矩形區域。
方法1:直接計算
遍歷所有的矩形區域,找出其中的最大值,其中遍歷的話複雜度為O(M^2 * N^2),假設二維陣列為M行N列。
其中怎麼計運算元矩陣的和呢?通過預處理,我們可以再O(1)的時間內算出。具體看下面的程式碼:
arrSum函式即做預處理,得到陣列p,p[i][j]表示已Rect(0, 0, i-1, j-1)矩形區域的總和。有了p陣列就可以直接計算出任意矩形的總和。
//計算2維陣列的最大和子矩陣
//直接計算:p[i][j]表示{0,0,i,j}的子矩陣的和;利用p可以快速求出sum{starti,startj,endi,endj}
public static void max2Sum_1(int[][] a,int m,int n){
int[][] p=new int[m+1][n+1];
//計算p矩陣
p[0][0]=0;
for(int i=1;i<m;i++){
p[i][0]=0;
}
for(int j=1;j<n;j++){
p[0][j]=0;
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
p[i][j]=p[i-1][j]+p[i][j-1]+a[i-1][j-1]-p[i-1][j-1];
}
}
for(int i=0;i<m+1;i++){
for(int j=0;j<n+1;j++){
System.out.print(p[i][j]+"\t");
}
System.out.println();
}
int si=0,sj=0,ei=0,ej=0;
//遍歷所有子矩陣
int ans=Integer.MIN_VALUE;
for(int i=1;i<=m;i++){ //行 從0到m
for(int j=1;j<=n;j++){ //列開始 從0到n
for(int endi=i;endi<=m;endi++){ //行結束 從i到m
for(int endj=j;endj<=n;endj++){
int sum=p[endi][endj]-p[i-1][endj]-p[endi][j-1]+p[i-1][j-1]; //子矩陣:從i,j開始到endi,endj
if(sum>ans){
ans=sum;
si=i;
sj=j;
ei=endi;
ej=endj;
System.out.println(ans+" "+si+" "+sj+" "+ei+" "+ej);
}
}
}
}
}
System.out.println(ans);
System.out.println(si+" "+sj+" "+ei+" "+ej);
}
方法2: 轉化為一維陣列計算
將每列中的各行相加,得到一個一維陣列,轉化求一維陣列的最大子陣列;
對矩陣,壓縮行,將每個子矩陣轉換化為一維陣列,進行求解;
子矩陣的高度:從1行到m行==所以需要遍歷所有的行;為減少遍歷的行數;==當m>n時,進行矩陣逆,
實現
public static void max2Sum_2(int[][] a,int m,int n){
if(m>n){
a=reverse(a);
int tmp=m;
n=m;
m=tmp;
}
//求出每一列中從第一行到第i行的和
int[][] p=new int[m+1][n+1];
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
p[i][j]=p[i-1][j]+a[i-1][j-1];
}
}
//求每個子陣列的和
int maxSum=Integer.MIN_VALUE;
int sum=0;
int si=0,sj=0,ei=0,ej=0;
for(int h=1;h<=m;h++){ //子矩陣的高度
for(int i=1;i+h-1<=m;i++){//子矩陣從i行開始,到endLine結束
int endLine=i+h-1;
sum=maxSum_2(p,i,endLine,n);
if(sum>maxSum){
maxSum=sum;
}
}
}
System.out.println(maxSum);
}
//求一維陣列的最大子陣列
private static int maxSum_2(int[][] p, int startLine, int endLine,int n) {
int maxSum=p[endLine][1]-p[startLine-1][1];//初始化最大子陣列和為第一列的和;
int sum=maxSum;
for(int i=2;i<=n;i++){
int num=p[endLine][i]-p[startLine][i];
if(sum<0){
sum=num;
}else{
sum+=num;
}
if(sum>maxSum){
maxSum=sum;
}
}
return maxSum;
}
private static int[][] reverse(int[][] a) {
int m=a.length;
int n=a[0].length;
int[][] newArr=new int[n][m];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
newArr[j][i]=a[i][j];
}
}
return newArr;
}
相關推薦
動態規劃_連續子數組的最大和
但是 == 向量 常常 ret pub num 負數 測試 題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是
動態規劃問題系列---連續子陣列(二維)的最大和
題目1 一維陣列的連續子陣列的最大和 輸入一個整型陣列,數組裡有正數也有負數。陣列中一個或連續的多個整陣列成一個子陣列。求所有子陣列的和的最大值。要求時間負責度為O(n)。 分析 假如輸入陣列為{1,-2,3,10,-4,7,2,-5},我們嘗試從頭
動態規劃:連續子陣列的最大和
這個題目寫了不下三遍了,次次寫還次次想不起來,想起來也還寫好幾遍才能寫對,求一串陣列的最大最大子序列和,用動態規劃的方法,簡直不要太高效。 比如下面這個陣列{1,-2,3,10,-4,7,2,-5},最大連續子陣列是{3,10,-4,7,2}和為
求陣列的連續子陣列之和的最大值(一維二維)
求陣列的連續子陣列之和的最大值 輸入一個N個元素的整型陣列,數組裡有正數也有負數。陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。求所有子陣列的和的最大值。 例如輸入的陣列為-9 -3 -2 2 -1 2 5 -7 1 5,和最大的子陣列為
【LeetCode & 劍指offer刷題】動態規劃與貪婪法題4:42 連續子數組的最大和(53. Maximum Subarray)
offer pla style other res another () nor pro 【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) 53. Maximum Subarray Given an integer array nu
連續子數組的最大和(基於動態規劃)
動態 pty ostream style http 還要 clu ons 連續子數組 題目 輸入一個整型數組,數組裏有正數也有負數。數組中一個或連續的多個整數組成一個子數組。求所有子數組的和的最大值。要求時間復雜度為O(n)。例如輸入的數組為{1,-2,3,10,-4,
求陣列的連續子陣列之和的最大值
同一個問題:http://blog.csdn.net/witsmakemen/article/details/17740933 一個有N個整數元素的一維陣列{A[0],A[1],....,A[N
連續子數組的最大和
println 宋體 for 中間 原來 動態規劃法 family 元素 oid 方法一:舉例分析數組的規律 例如數組{1,-2,3,10,-4,7,2,-5} 分析:循環遍歷數組,初始累加和為0。第一步,和為1.第二步,和為-1;第三步,和小於0,如果用-1加上3
求連續子數組的最大和
align div 置0 color 最大的 求解 for 技術分享 分享 一、題目: 這是一道考的爛的不能再爛的題目,但是依然有很多公司樂於將這樣的題目作為筆試或面試題,足見其經典。 問題是這樣的:一個整數數組中的元素有正有負,在該數組中找出一個連續子數組,要求該連
30連續子數組的最大和
for max 很好 例如 desc div 最大 今天 需要 題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負
【劍指offer】42、連續子數組的最大和
class 分享 因此 eat 組成 連續 最大和 累加 ret 題目 輸入一個整型數組,數組裏有正數也有負數。數組的一個或連續多個整數組成一個子數組。求所有子數組的最大和。要求時間復雜度為O(n) 思路一 試著從頭到尾累加每個數字,若發現有子數組和小於零,則加上後面的數字
劍指offer-連續子數組的最大和
更新 ++ += 找到 最終 gin spa 計算機專業 gre 題目:連續子數組的最大和 題目描述:HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題
python實現連續子數組的最大和
http tom 測試 mathjax 治法 bottom reat 所有 title 題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決
劍指offer--43.連續子數組的最大和
color pub 時間限制 scribe 返回 col coder 但是 mut 最大子段和,最大能取所有 ---------------------------------------------------------------- 時間限制:1秒 空間限制:32
一維、二維 最大連續子陣列和
演算法導論中的一個題目,上次面試題中被擴充套件到了二維和二維環形陣列,記錄下以供參考。一、 一維連續子陣列 最大和 問題描述:給定一個一維陣列,求其中連續子陣列和的最大值。 樣
《劍指offer》系列 連續子陣列的最大和(Java)
連結 牛客:連續子陣列的最大和 題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊
《劍指offer》系列 連續子陣列的最大和(Java)
連結 題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如
Java實驗——輸出二維數組連續二維子數組的最大和
http ring list static main 整理 右下角 只需要 image 該算法思路,根據我博客裏面一維子數組求和的思路,可以用一個新的二維數組對該二維區域的數組進行求和,例如新的二維數組的第5個位置,就代表從1到5斜對角線的塊狀區域的和,即1,2,4,
一個整形陣列中有正數也有負數,陣列中連續一個或多個組成子陣列,每個子陣列都有一個和,求所有子陣列中和的最大值
本文只作為學習筆記,如若侵權請告知,一定及時刪除 題目 輸入一個整型陣列,數組裡有正數也有負數。陣列中一個或者連續的多個整陣列成一個字陣列。求所有字陣列的和的最大值。要求時間複雜度為O(n)。例
程式設計之美8:求陣列的子陣列之和的最大值
1: int MaxSum(int *A, int n) { int maximum = -INF; int sum; for (int i = 0; i < n; i++) { sum = 0; for (int j = i;