面试题5:求子数组的最大和
面试题五:求子数组的最大和
5.求子数组的最大和
题目:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为 O(n)。
a[] = {-2,3,-1,4,-7,-3,4,5,-2}
像这个数组的最大子数组是{4,5}
思路一:这种情况时间复杂度大于0(n);
-2,3,-1,4,-7,-3,4,5,-2
a.开辟两个下标值,一个start,一个end,start指向最大子数组的头部,end指向最大子数组的尾部。初始化让start=0,end=0,都指向a[0].
b.首先找到end的位置,当end指向的是一个正数,直接end++;如果end指向的负数,判断负数右边有没有和比这个负数的绝对值大的数,如果有则让end=i;
c.找到end的位置后,下面去确定start的位置就好确定,只要找出从下标0到end处的所有子数组,中哪个是最大的。
package com.wukung.blog; /** * @author WuKung * @csdnURL http://blog.csdn.net/wu_kung/ * @createdDate 2014-4-10 下午9:34:27 */ public class MaxSubSequence { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int a[] = { -3, 1, 3, -1, -4, 0, -10, 11, 7, -5 }; int max = 0; int b = 0, s = 0; for (int i = 0; i < a.length; i++) { if (a[i] >= 0) { b = i; } else { int temp; int sum=0; for (temp = i; temp < a.length; temp++) { sum += a[temp]; if (sum >= 0) { b = i; break; } } } } int t = a[b]; max = a[b]; s=b; for (int i = b - 1; i >= 0; i--) { t += a[i]; if (max <= t) { s = i; max = t; } } for (int j = s; j <= b; j++) { System.out.print(a[j] + " "); } } }
思路二:时间复杂度O(n)的算法
其实算法很简单,当前面的几个数,加起来后,b<0后,
把 b 重新赋值,置为下一个元素,b=a[i]。
当 b>sum,则更新 sum=b;
若 b<sum,则 sum 保持原值
package com.wukung.blog; /** * @author WuKung * @csdnURL http://blog.csdn.net/wu_kung/ * @createdDate 2014-4-10 下午11:28:26 */ public class MaxTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int[] a = {-2,3,-1,4,-7,-3,4,5,-2}; System.out.println("输出最大子数组序列"); System.out.println(maxSum(a, a.length)); } public static int maxSum(int[] a, int n) { int sum=0; int b=0; int start=0,end=0; //针对数组全部为负数的判断。 int nTemp=a[0]; for(int j=1; j<n; j++) { if (nTemp<a[j]) nTemp=a[j]; } if (nTemp<0) return nTemp; for(int i=0; i<n; i++) { if(b<0){ start=i; b=a[i]; } else b+=a[i]; if(sum<b){ end=i; sum=b; } } for(int k=start;k<=end;k++){ System.out.print(a[k]+" "); } System.out.println(); System.out.println("输出最大子数组的和:"); return sum; } }