leetcode 21天动态规划入门——从0到0.5【Day07】请叫我股神~

leetcode 21天动态规划入门——从0到0.5【Day07】请叫我股神!

写在前面

圣诞节后的第一天,来到了动态规划的鼻祖题,买卖股票的冷冻期~要想成股神,dp少不了,那就让我们今天来炒炒股!冲啊!

题目

题目一

  1. 最佳观光组合
给你一个正整数数组 values,其中 values[i] 表示第 i 个观光景点的评分,
并且两个景点 i 和 j 之间的 距离 为 j - i。
一对景点(i < j)
组成的观光组合的得分为 values[i] + values[j] + i - j ,
也就是景点的评分之和 减去 它们两者之间的距离。
返回一对观光景点能取得的最高分。

示例1:

输入:values = [8,1,5,2,6]
输出:11
解释:i = 0, j = 2, 
values[i] + values[j] + i - j = 8 + 5 + 0 - 2 = 11

示例2:

输入:values = [1,2]
输出:2
提示

2 <= values.length <= 5 * 10^4
1 <= values[i] <= 1000

思路
经典的动态规划题:
主要麻烦的就是要考虑其滚动数组记录的最大值。

观察示例 :
维护一个dp数组用来记录到达从0到i的最大经典得分的值
再来一个变量max,滚动记录最大值

故此能得到状态转化方程:

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

滚动数组中的变量:

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

代码实现
class Solution {
    public int maxScoreSightseeingPair(int[] values) {
        int dp[] = new int [values.length+1];
        //当只有一个景点时,其最大的景点得分就是values[0] + 0 - 0;
        dp[0] = values[0] + 0;
        int max = 0;
        for (int j = 1 ;j<values.length;j++){
        	//用来记录当前的最大得分
            max = Math.max(max,dp[j-1]+values[j]-j);
            // 动态转化方程
            dp[j] = Math.max(dp[j-1],values[j]+j);
        }
        return max;
    }
}
执行结果

在这里插入图片描述

代码优化

至少思路简单但是肯定能优化 按照昨天学的知识 将一个变量来代替我们维护的数组。

class Solution {
    public int maxScoreSightseeingPair(int[] values) {
    	//利用score来代替我们的dp数组用到了贪心算法
        int max = 0 ,score = values[0] + 0;
        for (int j = 1 ;j <values.length;j++ ){
            max = Math.max(max,score + values[j] - j);
            score = Math.max(score,values[j] + j);
        }
        return max;
    }
}

在这里插入图片描述

题目二

  1. 买卖股票的最佳时机
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 
卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。
如果你不能获取任何利润,返回 0 。
示例

示例1:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入
,在第 5 天(股票价格 = 6)的时候卖出,
最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 
     因为卖出价格需要大于买入价格;
     同时,你不能在买入前卖出股票。

示例2:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
提示

1 <= prices.length <= 10^5
0 <= prices[i] <= 10^4

思路

这道题相比于之前的题需要进行分类判断。
当你持有股票的时候与当你没持有股票的时候两种情况

  • 当你今天未持有股票时,①前一天也没有持有股票的时候。②你可以通过卖出当天股票来获利prices[i] 取最大值。
  • 当你今天持有股票时的情况①是昨天本来就持有股票②或者今天买入股票花费prices[i]的钱取得最大值。
  • dp[i][0] 表示第i天持有股票所得现金。
  • dp[i][1] 表示第i天不持有股票所得最多现金
代码实现
class Solution {
    public int maxProfit(int[] prices) {
        int dp[][] = new int [prices.length][2];
        //当第一天未持有股票时的现金
        dp[0][0] = 0;
        //第一天持有股票时候需要花费prices[0]来购买当天的股票
        dp[0][1] = -prices[0];
        for (int i = 1;i< prices.length;i++){
        	//动态转化方程 当持有股票时 最大获利  当天未持有股票的最大收益
            dp[i][0] = Math.max(dp[i-1][0],prices[i]+dp[i-1][1]);
            dp[i][1] = Math.max(dp[i-1][1],-prices[i]);
        }
        //返回的是到达最后一天没有持有股票时候 会有 最大获利
        return dp[prices.length-1][0];
    } 
}
执行结果

在这里插入图片描述

题目三

  1. 买卖股票的最佳时机 II
给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。
你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例

示例1:

输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,
在第 3 天(股票价格 = 5)的时候卖出, 
这笔交易所能获得利润 = 5-1 = 4 。
     随后,在第 4 天(股票价格 = 3)的时候买入,
     在第 5 天(股票价格 = 6)的时候卖出, 
     这笔交易所能获得利润 = 6-3 = 3 。

示例2:

输入: prices = [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,
在第 5 天 (股票价格 = 5)的时候卖出, 
这笔交易所能获得利润 = 5-1 = 4 。
     注意你不能在第 1 天和第 2 天接连购买股票,
     之后再将它们卖出。
     因为这样属于同时参与了多笔交易,
     你必须在再次购买前出售掉之前的股票。
提示

1 <= prices.length <= 3 * 10^4
0 <= prices[i] <= 10^4

思路

这道题和上一道题思路相通,唯一区别就是可以买卖多次。
这重申一下dp数组的含义:

  • dp[i][0] 表示第i天持有股票所得现金。
  • dp[i][1] 表示第i天不持有股票所得最多现金
代码实现
class Solution {
    public int maxProfit(int[] prices) {
        int dp[][] = new int [prices.length][2];
        dp[0][0] = 0;
        dp[0][1] = -prices[0];

        for (int i = 1; i< prices.length;i++){
            dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1] + prices[i]);
            dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0] - prices[i]);
        }

        return dp[prices.length-1][0];
    }
}
执行结果

在这里插入图片描述

代码优化

不过这题说实在的是个脑筋急转弯
只要后一天别前一天的值大就加上该数值。

class Solution {
    public int maxProfit(int[] prices) {
        int ans=0;
        for(int i=1;i<=prices.length-1;i++)
        {
            if(prices[i]>prices[i-1])
            {
                ans+=prices[i]-prices[i-1];
            }
        }
        return ans;
    }
}

优化结果
在这里插入图片描述

写在后面

今天写完收工了哦~
动态规划已经练习到了第七天了!
不知不觉就到一个星期了
什么也不说了 坚持打卡每一天!
加油~热爱算法以及编程的你!

最后

每天进步点 每天收获点

愿诸君 事业有成 学有所获

如果觉得不错 别忘啦一键三连哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alascanfu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值