经典问题——最大连续子序列和
Maximum Subarray
Total Accepted: 15186
Total Submissions: 46442
My Submissions
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
.
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.
Have you been asked this question in an interview?
问题分析及解题思路:
经典的最大连续子序列和问题。 关键是分析问题,
首先想到的是在一个序列中可能存在多个连续的子序列和;
其次如何找出每个子序列和。
最后返回最大值即可
首先以第一个元素为一个子序列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;
}
}
备注:
1. Note1:这是代码的关键,
首先判断一个元素(也可以视为含有一个元素的子序列)是不是属于前面的子序列,应该看起与前面的加和是否比原来大,而不应考虑乘积,如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;
}
}
input.txt样例:
-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