动态规划再理解(53、121、174)

本次文档也是对动态规划的 再认识 。
之前写过一些文章,在处理动态规划问题的时候依据的思路是 :暴力搜索->加缓存->动态规划。相关文章有:算法八——动态规划动态规划——0-1背包问题动态规划——矩阵中的最短路径长度等等。
最近在看问题的时候发现,只要能明白暴力搜索是怎么搜索的,跟哪些条件有关系,不经过前面2个步骤也能写出动态规划方程。大家知道动态规划方程出来了,基本上问题就解决了。写下文章记录一下 。
如果看不出和哪些条件有关系,或者找不到动态转换关系,还是要依据步骤一步一步来。

1 53. Maximum Subarray

输入:int数组,有正有负
输出:找到所有子数组的和,返回其中最大的。
规则:子数组是一个连续的数组,至少包含一个元素。
例如:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

分析:对于任意一个元素nums[i],可以开启一个子序列{nums[i]},也可以追加在前一个数字子序列的后面{…nums[i-1],nums[i]}。
对于开启一个子序列的情况 ,子数组和=nums[i]。
对于追加的情况:目标是要求子数组和,所以只要之前以nums[i-1]为结尾的子数组的和+nums[i]即可。假设dp[i]=以nums[i]为结尾的子数组的最大的和。
最后结果在所有dp元素中查找最大值。

dp[i] = Math.max(nums[i],nums[i+dp[i-1]])

动归特征:与前一个元素相关;与以前一个元素为结尾的子数组最大和相关。
之后就是写代码了。

class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        dp[0] = nums[0];
        int max = dp[0];
        for(int i=1;i<n;i++){
            dp[i] = Math.max(nums[i],dp[i-1]+nums[i]);
            max = Math.max(max,dp[i]);
        }
        return max;
    }
}

进一步空间优化,可以自己思考。

2 121. Best Time to Buy and Sell Stock

输入:int数组,表示每天的股价。
输出:最大的盈利
规则:只可以买一次,卖一次。只能先买后卖。
例子:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: 在价格为1的时候买入,在价格为6的时候卖出。
分析:只能买卖一次,先买后卖,说明是要找 m a x ( p r i c e [ j ] − p r i c e [ i ] ) , j > i max(price[j]-price[i]),j>i max(price[j]price[i]),j>i。对于每一个j,只要找到 m i n ( p r i c e [ i ] ) , i = 0 , 1... j − 1 min(price[i]),i=0,1...j-1 min(price[i]),i=0,1...j1即可。

class Solution {
    public int maxProfit(int[] prices) {
        int maxProfit = 0;
        int minPrice = Integer.MAX_VALUE;
        for(int i=0;i<prices.length;i++){
            minPrice = Math.min(minPrice,prices[i]);
            maxProfit = Math.max(maxProfit,prices[i]-minPrice);
        }
        return maxProfit;
    }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值