给定一个数组,当中有正负数,求当中的一段“子数组”(即任意长度,连续的数字),使得这个“子数组”的和是所有“子数组”和中最大的,
如给定的数组为12, -8, 5, 66, -21, 0 ,35, -44,7,则最大的和的子数组为{12, -8, 5, 66, -21, 0 ,35},最大的和为89.
这就是个简单的典型的“动态规划”题目。
数组:x1,x2,x3,……xn
思路,首先是寻找最优子结构,这点要依靠一些经验规则。
这里的最优子结构就是
f(i)定义为以xi结尾的最大字串和。
那么f(i+1)就可以考虑
如果xi+1大于等于0或者f(i) + xi+1 > 0,那么f(i+1) = f(i) + xi+1;
如果f(i) + xi+1 <= 0,那么f(i+1) = 0;
递推公式就是有了。下面用DP的典型结构给出代码:
public class MaxSubSequence {
public static void main (String[] args) {
int[] input = new int[]{3,73,-95,42,43,29,-30,-87,74,-53,22,74,-91,-1,-27,-8,-14,26,-67,-74};
int[] fDp = new int[input.length]; //f for dp
//process first element
if (input[0] > 0)
fDp[0] = input[0];
for (int i = 1;i < input.length;++i){
if (fDp[i-1]+input[i] > 0)
fDp[i] = fDp[i-1]+input[i];
else
fDp[i] = 0;
}
//find the max value in fDp
int maxSun = 0;
for (int sum : fDp)
if (sum > maxSun)
maxSun = sum;
System.out.println("max sum : " + maxSun);
}
}
程序输出117
这里得到了正确结果,但是要求字串的位置还没实现,其实很简单,修改程序,从结果反推过程就可得到。
上面是个典型的一维DP结构的解法,算法复杂度是O(n),但是想更直接的求解,可以优化算法,不用显示创建DP数组。
class MaxSubSequence2{
public static void main (String[] args) {
int[] input = new int[]{3,73,-95,42,43,29,-30,-87,74,-53,22,74,-91,-1,-27,-8,-14,26,-67,-74};
int fst = -1,snd = -1,tFst = 0,tSnd = 0,maxSum = 0,currSum = 0;
for (;tSnd < input.length;++tSnd){
currSum += input[tSnd];
if (currSum > maxSum){
maxSum = currSum;
fst = tFst;
snd = tSnd;
}
if (currSum < 0){
currSum = 0;
tFst = tSnd+1;
}
}
System.out.println("max sum : " + maxSum + " from " + fst + " to " + snd);
}
}
考虑全负数的数组,修改一点就能满足。
class MaxSubSequence2{
public static void main (String[] args) {
int[] input = new int[]{-95,-30,-87,-53,-91,-1,-27,-8,-14,-67,-74};
int fst = -1,snd = -1,tFst = 0,tSnd = 0,maxSum = 0,currSum = 0;
int maxNum=Integer.MIN_VALUE;
for (;tSnd < input.length;++tSnd){
currSum += input[tSnd];
if(input[tSnd]>maxNum){
maxNum=input[tSnd];
}
if (currSum > maxSum){
maxSum = currSum;
fst = tFst;
snd = tSnd;
}
if (currSum < 0){
currSum = 0;
tFst = tSnd+1;
}
}
if(currSum==0){
System.out.println("max sum : " + maxNum + " It's [" +maxNum+"]" );//显示第一个最大负数
return;
}
System.out.println("max sum : " + maxSum + " from " + fst + " to " + snd);
}
}
如给定的数组为12, -8, 5, 66, -21, 0 ,35, -44,7,则最大的和的子数组为{12, -8, 5, 66, -21, 0 ,35},最大的和为89.
这就是个简单的典型的“动态规划”题目。
数组:x1,x2,x3,……xn
思路,首先是寻找最优子结构,这点要依靠一些经验规则。
这里的最优子结构就是
f(i)定义为以xi结尾的最大字串和。
那么f(i+1)就可以考虑
如果xi+1大于等于0或者f(i) + xi+1 > 0,那么f(i+1) = f(i) + xi+1;
如果f(i) + xi+1 <= 0,那么f(i+1) = 0;
递推公式就是有了。下面用DP的典型结构给出代码:
























这里得到了正确结果,但是要求字串的位置还没实现,其实很简单,修改程序,从结果反推过程就可得到。
上面是个典型的一维DP结构的解法,算法复杂度是O(n),但是想更直接的求解,可以优化算法,不用显示创建DP数组。





















考虑全负数的数组,修改一点就能满足。































