最大子列和問題

2021-09-13 21:45:13 字數 3729 閱讀 6004

給定k個整數組成的序列,「連續子列」被定義為,其中 1≤i≤j≤k。「最大子列和」則被定義為所有連續子列元素的和中最大者。例如給定序列,其連續子列有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。

本題旨在測試各種不同的演算法在各種資料情況下的表現。各組測試資料特點如下:

資料1:與樣例等價,測試基本正確性;

資料2:102個隨機整數;

資料3:103個隨機整數;

資料4:104個隨機整數;

資料5:105個隨機整數;

輸入格式:

輸入第1行給出正整數k (≤100000);第2行給出k個整數,其間以空格分隔。

輸出格式:

在一行中輸出最大子列和。如果序列中所有整數皆為負數,則輸出0。

輸入樣例:

6

-2 11 -4 13 -5 -2

輸出樣例:

演算法一:用三重迴圈,外重迴圈遍歷子列左端位置,中間層迴圈遍歷子列右端位置,內層迴圈對i到j的子列進行求和。

/**

* 演算法一,三重迴圈

* @param a 陣列a

* @param k 陣列a的長度

* @return maxsum 最大子列和

*/private static int maxsubseqsum1(int a, int k)

}} return maxsum;

}

很明顯這個演算法的時間複雜度為**提交之後,5個測試用例僅能通過兩個,看來演算法還需要在完善,如圖:

演算法二:

用兩重迴圈,外重迴圈遍歷子列左端位置,內層迴圈遍歷子列右端位置,對於相同的i,不同的j,只要在j-1次迴圈的基礎上累加1項即可,減少了一層迴圈。

/**

* 演算法二,用兩重迴圈

* @param a 陣列a

* @param k 陣列a的長度

* @return maxsum 最大子列和

*/private static int maxsubseqsum2(int a, int k)

}} return maxsum;

}

演算法二減少了一層迴圈,很明顯這個演算法的時間複雜度為**提交之後,5個測試用例僅能通過4個,當資料規模達到105個隨機整數時,記憶體超限了,當如圖:

演算法三:

用分治法來處理,每次將序列從中間劃分開,分別處理左子列、右子列、以及跨分界線的最大子列和,返回三者中的最大值。

舉個例子:

* 演算法三,保持與前2種演算法相同的函式介面

* @param a

* @param k

* @return

*/private static int maxsubseqsum3(int a, int k)

/*** 返回3個整數中的最大值

* @param a

* @param b

* @param c

* @return

*/private static int max3(int a,int b,int c)

/*** 分治法求a[left]到a[right]的最大子列和

* @param a 陣列a

* @param left

* @param rignt

* @return

*/private static int divideandconquer(int a, int left, int right) else

} //下面是"分"的過程

center = (left + right)/2; //找到中分點

//遞迴求得兩邊子列的最大和

maxleftsum = divideandconquer(a, left, center);

maxrightsum = divideandconquer(a, center+1, right);

//下面求跨分界線的最大子列和

//從中間往左邊掃瞄

maxleftbordersum = 0;

leftbordersum = 0;

for (int i = center; i >= left; i--)

} //從中間往右邊掃瞄

maxrightbordersum = 0;

rightboedersum = 0;

for (int i = center+1; i <= right; i++)

}

//下面返回"治"的結果

return max3(maxleftsum, maxrightsum, maxleftbordersum+maxrightbordersum);

}由於分治法將問題劃分為兩個子問題,每個子問題的規模都為原來的一半,最後還要加上處理跨分界線的最大子列和的規模(即將整個序列掃瞄一遍,為n),所以演算法的時間複雜度為o(n logn)。

演算法四:

/**

* @param a 陣列a

* @param k 陣列a的元素個數

* @return maxsum 最大子列和

*/private static int maxsubseqsum4(int a, int k) else if (thissum < 0)

} return maxsum;

}

演算法四只有一層for迴圈,時間複雜度是o(n)。也是這個問題所能達到的最佳時間複雜度了,畢竟,要求出序列的最大子列和至少的把整個掃面一遍吧。這種方法可以算是近乎完美的一種求解最大子列和的演算法。

這種演算法效率之所以如此高,是因為任何負的子串行都不可能是最有子串行的字首,所以我們可以知道,只要是首位元素為負數的肯定不是最大子列的組成部分,我們可以將其拋棄。即如果某個子列的首位為負數,那麼它一定要借助後面的非負數改進。

而且這種演算法還有一種優點就是,它只對資料掃瞄一次,在任何時刻,演算法都可以對它已經讀入的資料給出正確的答案。

另外,給出呼叫以上演算法的main()方法:

public static void main(string args) 

//int ans = maxsubseqsum1(a,k);

//int ans = maxsubseqsum2(a,k);

//int ans = maxsubseqsum3(a,k);

int ans = maxsubseqsum4(a,k);

system.out.println(ans);

}

最大子列和問題

給定k個整數組成的序列,連續子列 被定義為,其中 1 i j k。最大子列和 則被定義為所有連續子列元素的和中最大者。例如給定序列,其連續子列有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。輸入格式 輸入第1行給出正整數 k 100000 第2行給出k個整數,其間以空格分隔。輸出格式...

最大子列和問題

給定k個整數組成的序列,連續子列 被定義為,其中 1 i j k。最大子列和 則被定義為所有連續子列元素的和中最大者。例如給定序列,其連續子列有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。輸入格式 輸入第1行給出正整數 k 100000 第2行給出k個整數,其間以空格分隔。輸出格式...

最大子列和問題

給出乙個序列,求出最大子列和。演算法一 long maxsum int a,int n return maxsum 這是乙個窮舉的演算法,有三個巢狀的for迴圈,時間複雜度為o n 3 在計算的時候有很多不必要的重複項,例如當i 0,j 3時,和的計算為 a 1 a 2 a 3 當i 0,j 4時,...