分治法Q1——最大子序列和
问题描述(最大区段问题)
给定一个长度为n的整数序列,求它的最大连续子序列和
-2,1,-3,4,-1,2,1,-5,4 最大连续子序列和为4+(-1)+2+1=6
注意题目说最大没有说最长
package 分治法;
public class 最大连续子序列 {
/**解法一:暴力枚举法
* 时间复杂度 O(n^3)
* 空间复杂度 O(1)
* @param nums
* @return 返回子区段最大值
*/
public int maxSubArray(int[] nums) {
int max=Integer.MIN_VALUE;
//前两个for 切片 切出[begin,end]区间的子序列
for(int begin=0;begin<nums.length;begin++) {
for(int end=begin;end<nums.length;end++) {
//将该区段和统计起来
int sum=0;
for(int i=begin;i<=end;i++) {
sum+=nums[i];
}
//比较得出最大区段和
max=Math.max(max, sum);
}
}
return max;
}
/**解法二:带点优化的暴力枚举法
* 发现上面穷举时出现大量重复计算
* 如-2 1 -3 4 -1 2 1 -5 4
* 计算-2到2 之后计算-2到1 又重复计算了-2到d第二个2 这一段
* 可以将这一段结果保存利用下来从而减低复杂度
* 时间复杂度 O(n^2)
* 空间复杂度 O(1)
* @param nums
* @return 返回子区段最大值
*/
public int maxSubArray1(int[] nums) {
int max=Integer.MIN_VALUE;
//前两个for 切片 切出[begin,end]区间的子序列
for(int begin=0;begin<nums.length;begin++) {
int sum=0;
for(int end=begin;end<nums.length;end++) {
sum+=nums[end];
//比较得出最大区段和
max=Math.max(max, sum);
}
}
return max;
}
public int maxSubArray2(int[] nums) {
//判掉不合理情况
if(nums.length<1||nums==null) return 0;
return maxSubArray2(nums,0,nums.length);
}
/**maxSubArray2(int[] nums, int begin, int end)
* 功能是求出[begin,end)的最大子序列和
*分治法将[begin,end) 分为[begin,mid) [mid,end)
*最大子序列区段为[i,j]
* */
public int maxSubArray2(int[] nums, int begin, int end) {
if(end-begin<2) {//递归出口 当区段被切割到只有一个元素时 那么此时最大子序就是它本身
return nums[begin];//[begin,end)左闭右开 不能填nums[ends]
}
int mid=(begin+end)>>1;
//第一种情况[i,j)在左半段
//左半部分从mid-1开始从右往左扫
int leftSum=0;
int leftMax=Integer.MIN_VALUE;
for(int i=mid-1;i>=begin;i--) {
leftSum+=nums[i];
leftMax=Math.max(leftMax, leftSum);
}
//第二种情况[i,j)在右半段
//右半部分从mid开始从左往右扫
int rightSum=0;
int rightMax=Integer.MIN_VALUE;
for(int i=mid;i<end;i++) {
rightSum+=nums[i];
rightMax=Math.max(rightMax, rightSum);
}
//第三种情况[i,j)左半段和右半段都有
int max=leftMax+rightMax;
System.out.println(leftMax+" " +max+" "+rightMax);
return Math.max(max,
Math.max(maxSubArray2(nums,begin,mid),
maxSubArray2(nums, mid,end))
);
}
public static void main(String[] args) {
最大连续子序列 a=new 最大连续子序列();
int []nums=new int[]{-2,1,-3,4,-1,2,1,-5,4};
//int []nums=new int[]{3,1,-1,4,6,-8,9,-5,4};
System.out.println(a.maxSubArray(nums));
System.out.println(a.maxSubArray1(nums));
System.out.println(a.maxSubArray2(nums));
}
}
分治法解最大子序列和过程
动态规划解法解最大子序列和先留个坑在这里