vlambda博客
学习文章列表

算法之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


算法二:动态规划法

采用动态规划法降低算法的时间复杂度,算法描述如下:

  1. 最大子数组包含arr[0];

  2. 最大子数组为arr[0];

  3. 最大子数组不包含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)。