分治法之最大子序列和

分治法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));
		
	}

}

分治法解最大子序列和过程
分治法解最大子序列和过程  最后最大子序列和为黑色字体中的6动态规划解法解最大子序列和先留个坑在这里

发布了21 篇原创文章 · 获赞 0 · 访问量 481

猜你喜欢

转载自blog.csdn.net/weixin_44855907/article/details/104592868