动态规划 最大子序列

最大子序列

问题描述:

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

问题分析:

其实这道题是典型的动态规划问题,也可以使用循环来解决这个问题,但是效率会很低下,但是数组的内容会对你的算法有很大的影响,比如 
全为 负数,再比如,只有一个数据,这些都是特殊情况

在这里留下了几种方法,可以参考

--解决不了数组全为负数的情况
1,三重循环的暴力求解
2,双重循环的暴力求解
3,时间复杂度为o(n)的普通解法
4,时间复杂度为o(n)的动态规划

--可以解决数组全为负数的情况
5, 适应多种情况数组的动态规划解法

代码展示(已验证):

public class maxSubArray 
{
	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		int[] nums = {-2,1,-3,4,-1,2,1,-5,4};
		
		//开始位置的选择 两个数加在一起 大于0
		//结束位置的选择,几个数字加在一起大于零或者 前面是大数加了之后变小了不要
		//如果全小于0,可以找出数组中最大的输出
		
		// 没能解决数组全为负的问题
		System.out.println("暴力求解 "+maxsubarray1(nums));
		System.out.println("暴力求解升级版 "+maxsubarray2(nums));
		System.out.println("o(n)的优化算法 "+maxsubarray3(nums));
		System.out.println("o(n)的动态规划算法 "+maxsubarray4(nums));
		//可解决数组全为负的情况
		System.out.println("o(n)的动态规划算法,可解决数组全为负的情况 "+maxsubarray5(nums));
	}

1,三重暴力求解 列出所有情况

	// 1,暴力求解 列出所有情况
	public static int maxsubarray1(int[] nums) {
		int maxsum=0;
		for(int i=0; i<nums.length-1; i++){
			
			for(int j=i; j<nums.length; j++) {
				int tempsum=0;
				for(int k=i; k<=j; k++)
					tempsum += nums[k];
				if(tempsum > maxsum)
					maxsum = tempsum;
			}
		}
		return maxsum;
	}

2, o(n^2)的暴力求解改进算法


	//2, o(n^2)的暴力求解改进算法
	public static int maxsubarray2(int[] nums) {
		int maxsum = 0;
		for(int i=0; i<nums.length; i++) {
			int tempsum =0;
			for(int j=i; j<nums.length; j++) {
				tempsum += nums[j];
				
				if(tempsum > maxsum)
					maxsum = tempsum;
			}
		}
		return maxsum;
	}

3,o(n)的普通优化算法

	//3,o(n)的优化算法(解决不了数组全为负的问题)
	public static int maxsubarray3(int[] nums) {
		int maxsum=0,tempsum=0;
		for(int i=0; i<nums.length; i++) {
			tempsum+=nums[i];
			
			if(tempsum > maxsum)
				maxsum = tempsum;
			else if(tempsum < 0)
				tempsum =0;
		}
		return maxsum;
	}

4, o(n)的动态规划算法

	//4, o(n)的动态规划算法
	/*
	 * 求解思路:用sum(j) 表示 a1 到 aj 的和,很容易求出动态规划的递归表达式
	 * sum(j) = max(sum(j-1)+aj,aj)
	 * 可以清楚的返回最佳连续子序列和的起始位置和终点位置
	 */
	public static int maxsubarray4(int[] nums) {
		int maxsum=0,tempsum=0,begin=0;
		
		for(int i=0; i<nums.length; i++) {
			if(tempsum > 0)
				tempsum += nums[i];
			else {
				tempsum = nums[i];
				begin = i;
			}
			if(tempsum > maxsum)
				maxsum = tempsum;
			//可以在这里获取最佳连续子序列的起点位置 begin 和 终点位置 i
		}
		return maxsum;
	}

5,动态规划,可解决数组全为负的情况

	//5,动态规划,可解决数组全为负的情况
	public static int maxsubarray5(int[] nums) {
        if(nums.length < 1) return 0;
        if(nums.length == 1) return nums[0];
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        int result = dp[0];
        for(int i=1; i<nums.length; i++){
            dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);
            result = Math.max(result,dp[i]);
        }
        return result;
	}
}

泡泡:

动态规划的思想很重要,学起来也更难,但是冰冻三尺非一日之寒,还是要多多努力

猜你喜欢

转载自blog.csdn.net/qq_42124842/article/details/92393337
今日推荐