最大連續子數組和: 給定n個整數(可能爲負數)組成的序列a[1],a[2],a[3],…,a[n],求該序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。當所給的整數均爲負數時定義子段和爲0,依此定義,所求的最優值爲: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n 例如,當(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)時,最大子段和爲20。java
該題目給的要求是求數組的最大子數列和。 對於最大子數列和的問題,在時間複雜度爲O(n)的狀況下,求解時考慮兩個基本事實: 事實1: 對於一個從頭開始的子數列,若是這個數列的和小於0,那麼這個子數列不可能在所要求的最大子數列裏。 事實2: 對於一個首尾隨機的有序數列,數列和爲正向掃描的當前最大的子數列,若是加上下一個數後,數列的和小於0了,那麼原數列加上後一個數從而組成的數列就不會是最大連續子數列。此時應該保持原數列的和的值,再向後尋找的時候須要將下一個數做爲查找的子數列的首項。 依照此想法,可得到下面的求解方法: 將數列從頭至尾依次掃描,逐次相加。每次相加的時候查看加和是否比已知的最大連續子數列和大。若是較大,則替換最大和,不然,查看加和是否爲負數。若是爲負數,則保留以前的最大和,同時將先前的數列清空,從下一個數開始從新相加,比較最大值。git
流程圖以下: github
根據流程圖可編寫出具體代碼。 對該算法的代碼以下:算法
public int GetMax() { int MaxNow = 0; int NumNow = 0; if(n < 0) { return -1; } for(int i = 0 ;i < n ;i++) { NumNow += NumList[i]; if(NumNow > MaxNow) { MaxNow = NumNow; } else if( NumNow < 0) { NumNow = 0; } } return MaxNow; }
可執行的代碼地址:github代碼api
選擇條件組合覆蓋方式。 由流程圖可知,該流程主要的判斷有四個: 1.對n的判斷: n<0; n>=0;數組
2.對i的判斷: i<n; i>=n;單元測試
3.對NumNow是否大於MaxNow的判斷: NumNow>MaxNow; NumNow<MaxNow;測試
4.對NumNow是否小於0的判斷: NumNow>0; NumNow<0;spa
因爲2中對i的判斷是在循環中進行的,並且是在n>0的狀況下必然發生的事情,因此能夠歸類爲對n的判斷。 在3和4中的對NumNow的判斷,能夠整合爲對NumNow>MaxNow、0<=NumNow<=MaxNow、NumNow<0三種狀況判斷。並且由於該判斷處在循環中,因此有一塊兒發生的可能。設計
全部可能的組合爲: 1.n<0; 2.n=0; 3.n>0;NumNow>MaxNow; 4.n>0;NumNow>MaxNow;0<=NumNow<=MaxNow; 5.n>0;NumNow<0; 6.n>0;NumNow>MaxNow;0<=NumNow<=MaxNow;NumNow<0; 7.n>0;0<=NumNow<=MaxNow; 8.n>0;0<=NumNow<=MaxNow;NumNow<0; 9.n>0;NumNow>MaxNow;NumNow<0;
因此設計測試樣例爲:
測試代碼以下:
package homework; import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; class NumListTest { @Test void testGetMax1() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {-1,-2,-3,-4,-5,-6}; assertEquals(0,a.GetMax()); } @Test void testGetMax2() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {-2,11,-4,13,-5,-2}; assertEquals(20,a.GetMax()); } @Test void testGetMax3() { NumList a = new NumList(); a.n = 0; a.NumList =new int[] {}; assertEquals(0,a.GetMax()); } @Test void testGetMax4() { NumList a = new NumList(); a.n = -1; a.NumList =new int[] {}; assertEquals(-1,a.GetMax()); } @Test void testGetMax5() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {1,3,4,5,6,7}; assertEquals(26,a.GetMax()); } @Test void testGetMax6() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {11,11,-4,-1,-1,-1}; assertEquals(22,a.GetMax()); } @Test void testGetMax7() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {0,0,0,0,0,0}; assertEquals(0,a.GetMax()); } @Test void testGetMax8() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {0,-1,-4,-5,-5,-2}; assertEquals(0,a.GetMax()); } @Test void testGetMax9() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {-1,3,-4,-5,-5,-2}; assertEquals(3,a.GetMax()); } }
測試代碼地址github代碼_測試
測試截圖以下: