经典问题——最大连续子序列和
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4]
,
the contiguous subarray [4,−1,2,1]
has the largest sum = 6
.
click to show more practice.
If you have figured out the O(n) solution, try coding another solution
using the divide and conquer approach, which is more subtle.
经典的最大连续子序列和问题。 关键是分析问题,
首先想到的是在一个序列中可能存在多个连续的子序列和;
其次如何找出每个子序列和。
最后返回最大值即可
首先以第一个元素为一个子序列S1,判断其后的元素j 属不属于S1,应根据元素j 加上 S1的和后,是否比原来的值大。
若sum(S1,j) > sum(S1);则把j添加进S1,往后继续扫描。。
若sum(S1,j) < sum(S1);则j 为另一个(如S2)子序列的开始,以含一个S2的新子序列开始继续扫描。
最后返回和最大的子序列。
最后要想到数组里面的元素可能全部或部分为负数、0、正数;注意一下是否会溢出。
此外对于“一个最大的连续子序列和 的两边的元素一定是正的”这句话是错的,若一个负数可以连接两个比较大的序列使总和最大,或者序列中全为负数就不对了。
Java源码:不改变数据A内元素值。
//时间复杂度O(n),空间复杂度O(1)
public class Solution {
public static int maxSubArray(int[] A) {
int maxSum = Integer.MIN_VALUE;
int curMaxSum = 0;
for (int i = 0; i < A.length; ++i) {
curMaxSum = Math.max(curMaxSum + A[i], A[i]);
maxSum = Math.max(curMaxSum, maxSum);
}
return maxSum;
}
}
首先判断一个元素(也可以视为含有一个元素的子序列)是不是属于前面的子序列,应该看起与前面的加和是否比原来大,而不应考虑乘积,如temp*A[i]>=0; 因为这就忽略了都为负数的话,不应该加在一起!分析清题意最重要。
2. 提交的代码开启来很简单漂亮,这都是修改过的。自己在做题的时候更应该重视逻辑和问题分析,等到代码work后在优化代码,写的漂亮一些。
3. 最大连续子序列和的动态规划中的状态为:当前状态i的最大子序列和。currentMaximumSum(i) = Max (currentMaximumSum(i-1) , currentMaximumSum(i-1) + A[i])。 另外,在每次更新状态i时的最大子序列和是,都更新以往计算过程中所有最大子序列的和的最大值。
附录:
原题地址:https://oj.leetcode.com/problems/maximum-subarray/
一个能独立跑的源码和样例:
源码:
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
public class MaximumSubarray {
public static void main(String args[]) throws IOException {
FileInputStream fis = new FileInputStream("input.txt");
System.setIn(fis);
// PrintStream ps = new PrintStream(new FileOutputStream("output.txt"));
// System.setOut(ps);
Scanner sc = new Scanner(System.in);
String line;
int lineNo = 1;
while (sc.hasNextLine()) {
line = sc.nextLine().trim();
String strs[] = line.split(",");
System.out.println(line);
int list[] = new int[strs.length];
for (int i = 0; i < strs.length; ++i) {
list[i] = Integer.valueOf(strs[i].trim());
}
System.out.println((lineNo++) + " : " + maxSubArray(list));
}
sc.close();
}
public static int maxSubArray(int[] A) {
int maxSum = Integer.MIN_VALUE;
int curMaxSum = 0;
for (int i = 0; i < A.length; ++i) {
curMaxSum = Math.max(curMaxSum + A[i], A[i]);
maxSum = Math.max(curMaxSum, maxSum);
}
return maxSum;
}
}
-1,-2
2,3
-2,-1
-2,0,1
1,0,-2
0,1,-2
-2,1,0
0, 0, -2, 0 ,0
0, 0, 2
-2, 1, -3, 4, -1, 2, 1, -5, 4
-2, 1, -3, 4, -1, 2