算法之1 | 最大子数组问题
问题描述:
一个n个元素的数组,其中有正数也有负数,求一个子数组,使其元素之和最大。
例如:数组{1,-2,4,8,-4,7,-1,-5},最大和的子数组为{4,8,-4,7},和为15。
算法一:“蛮力”法
枚举所有的子数组,求出和,找出和最大的子数组。代码如下:
import java.util.Scanner;public class maxSubArray {public static int maxSubArrayMethodTwo(int arr[]){int size =arr.length;int maxSum=Integer.MIN_VALUE;for(int i=0;i<size;i++){int sum=0;for(int j=i;j<size;j++){sum+=arr[j];if(sum>maxSum){maxSum=sum;}}}return maxSum;}public static void main(String[] args) {Scanner sc=new Scanner(System.in);int number=Integer.parseInt(sc.next());//number表示数组的长度int[] num=new int[number];//对数组元素循环赋值for(int i=0;i<number;i++){num[i]=(int)sc.nextInt();}System.out.println(maxSubArrayMethodTwo(num));}}
以上算法的时间复杂度为O(n^2)。
程序运行结果:
输入:8 1 -2 4 8 -4 7 -1 -5
输出:15
算法二:动态规划法
采用动态规划法降低算法的时间复杂度,算法描述如下:
最大子数组包含arr[0];
最大子数组为arr[0];
最大子数组不包含arr[0],问题转为求arr[1]至arr[n-1]的一个序列。
代码如下:
import java.util.Scanner;public class maxSubArray {public static int max(int m,int n){return m>n ? m :n;}public static int maxSubArrayMethodThree(int arr[]){int n=arr.length;int End[]=new int[n];int All[]=new int[n];End[n-1]=arr[n-1];All[n-1]=arr[n-1];End[0]=All[0]=arr[0];for(int i=1;i<n;i++){End[i]=max(End[i-1]+arr[i],arr[i]);All[i]=max(End[i],All[i-1]);}return All[n-1];}public static void main(String[] args) {Scanner sc=new Scanner(System.in);int number=Integer.parseInt(sc.next());//number表示数组的长度int[] num=new int[number];//对数组元素循环赋值for(int i=0;i<number;i++){num[i]=(int)sc.nextInt();}System.out.println(maxSubArrayMethodThree(num));}}
动态规划法的时间复杂度为O(n)。
