給定k個整數組成的序列,「連續子列」被定義為,其中 1≤i≤j≤k。「最大子列和」則被定義為所有連續子列元素的和中最大者。例如給定序列,其連續子列有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。
本題旨在測試各種不同的演算法在各種資料情況下的表現。各組測試資料特點如下:
資料1:與樣例等價,測試基本正確性;
資料2:102個隨機整數;
資料3:103個隨機整數;
資料4:104個隨機整數;
資料5:105個隨機整數;
輸入格式:
輸入第1行給出正整數k (≤100000);第2行給出k個整數,其間以空格分隔。
輸出格式:
在一行中輸出最大子列和。如果序列中所有整數皆為負數,則輸出0。
輸入樣例:
6輸出樣例: 演算法一:用三重迴圈,外重迴圈遍歷子列左端位置,中間層迴圈遍歷子列右端位置,內層迴圈對i到j的子列進行求和。-2 11 -4 13 -5 -2
/**
* 演算法一,三重迴圈
* @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時,...