题型:动态规划
方法1:暴力查找
循环遍历即可
class Solution {
public int maxSubArray(int[] nums) {
int max=Integer.MIN_VALUE,sum=0;
for(int i=0;i<nums.length;i++){
sum=0;
for(int j=i;j<nums.length;j++){
sum+=nums[j];
if(sum>max){
max=sum;
}
}
}
return max;
}
}
方法2:动态规划
设nums有n个数,f(i)为nums某一段连续子数组之和,如果f (i)的下一个nums比f (i)加上该nums大,那么该f (i)加上该nums肯定不是最大子序和,因此将pre从该nums重新指定并往后累加,比较f (i)数组中相对较大值来求出最大值
(官方参考代码理解)
class Solution{
public int maxsubarray(int[] nums)
{
int pre=0,max=-Integer.MAX_VALUE;
for(int i=0;i<nums.length;i++)
{
pre=Math.max(pre+nums[i],nums[i]);//将当前f(i)和下一个nums比较
max=Math.max(max,pre);//比较当前f(i)和上一个f(i-1)值
}
return max;
}
方法3:分治法
简单来说就是把数组不停对半分,类似二分法,只到不能再分为止。在每次对半分的同时,先求出左边的从最右边开始的最大子序和,记为lmax,在求出右边的从左边开始的最大子序和,记为rmax。由于左右两边是连续的,故可以求出总体子序值cmax=lmax+rmax;根据递归,当分到不能再分的时候,返回一个nums[start]到lsummax和rsummax;再返回到有四个数据的子集合,比较三者大小求出子序最大值;再返回到有八个数据的子集合,再求出最大值…以此类推。等同与法2中的求出一个f (i),然后比较f (i)数组中相对较大值求出最大值。
(非官方递归方法)
public Solution{
public int maxarray(int[] nums)
{
return maxdevide(int[] nums,0,nums.length-1);//返回要遍历的函数
}
public maxdevide(int[] nums,int start,int end)
{
if(start==end){
return nums[start];//当递归到不能分时返回,递归结束
}
int center=(start+end)>>1;
int lmax=Iteger.MIN_VALUE,rmax=Iteger.MIN_VALUE;
int lsummax=0,rsummax=0;
lsummax=maxdevide(nums,start,center);//进行递归直到只有一个数,返回到lsummax,右同理
rsummax=maxdevide(nums,center+1,end);
for(int i=center;i>=start;;i--)//求出左边最大子连续和
{
int l=0;
lmax=Math.max(l+nums[i],lmax);//必须包含左侧最右边一个子序列最大值,右同理
}
for(int i=center+1;i<=end;i++)//求出右边最大子连续和
{
int r=0;
rmax=Math.max(r+nums[i],rmax);
}
int dcross=lmax+rmax;//左右最大值相加值,连接左右区域
return Math.max(dcross,Math.max(lsummax,rsummax));//由小到大返回该子集和最大值
}