一:連續子數組的最大和
LeetCode 53 Maximum Subarray
題意:給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
定義dp[i]爲前i個數中的連續子數組的最大和。
狀態轉移方程爲:
d[i] = d[i-1]>=0 ? d[i-1]+nums[i] : nums[i]
if not nums: return 0
dp = [0]*len(nums)
dp[0] = nums[0]
res = nums[0]
for i in range(1, len(nums)):
dp[i] = max(dp[i-1]+nums[i], nums[i]) # dp[i] means the maximum subarray ending with A[i]
res = max(res, dp[i])
return res
優化空間複雜度:
public static int get(int[] array) {
int max = 0,temp = 0;
for (int i = 0; i < array.length; i++) {
temp += array[i];
if (temp < 0)
temp = 0;
if (max < temp)
max = temp;
}
return max;
}
二:循環列表中的子數組最大和
參考博客:https://blog.csdn.net/weixin_43320847/article/details/83045856
這個問題的解可以分爲兩種情況:
- 最大子數組沒有跨越 array[n-1] 到 array[0] (原問題)
- 最大子數組跨越 array[n-1] 到 array[0]
對於第二種情況,我們不妨換個思路,如果最大子序列跨越了 array[n-1] 到 array[0],那麼最小子序列肯定不會出現跨越 array[n-1] 到 array[0] 的情況。
所以,在允許數組跨界(首尾相鄰)時,最大子數組的和爲下面的最大值
max = { 原問題的最大子數組和,數組所有元素總值 - 最小子數組和 }
public class MaxSequence {
public static int getMax(int[] array) {
int max = 0,temp = 0;
for (int i = 0; i < array.length; i++) {
temp += array[i];
if (temp < 0)
temp = 0;
if ( max < temp)
max = temp;
}
return max;
}
public static int getMin(int[] array) {
int min = 0, temp = 0;
for (int i = 0; i < array.length; i++) {
temp += array[i];
if (temp > 0)
temp = 0;
if (temp < min)
min = temp;
}
return min;
}
public static int getLoopMax(int[] array) {
int max1 = getMax(array);
int min = getMin(array);
int temp = 0;
for (int i = 0; i < array.length; i++) {
temp += array[i];
}
return Math.max(max1, temp - min);
}
}