1.题目链接:121. 买卖股票的最佳时机
题目描述:
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
解法:
1.贪心:
①此题只能买买卖股票一次。我们可以用贪心的写法来做。即求左边最小的和右边最大的。
如何求?
①定义Low = MAX;result = 0;
②定义Low = min(Low,price[i])--- 就相当于在遍历的时候获取了从初始位置到当前位置的最小值。
③result = max(result,prices[i] - Low) --- 就相当于取最大右边。此时如果出现721这样的数值,那么result会一直是0,所以符合。
④最后返回result。
下面为代码(java):
2.动态规划:
①确定dp[][] 为什么是二维的?因为我们既要表示第几天也要表示该天是否持有股份的最大利润。所以是二维。故dp[i][0]表示的就是,第i天持有股份的最大利润。dp[i][1]表示的就是,第i天不持有股份的最大利润。
②递推公式:
dp[i][0] = ? 如果前面就持有了延续到这个位置,那就是dp[i-1][0];如果前面没有,就是新买入的,即 - prices[i] --- 因为只能买卖一次,所以如果买入的话就是-prices[i].
故dp[i][0] = max(dp[i-1][0] , -prices[i]);
dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i])---即前面不持有;前面持有,现在卖了。
③初始化:根据前面的值求的,所以dp[0][0] = -prices[0];dp[0][1] = 0;其他值无所谓,因为都是根据的是前面的值求的当前值,所以可以初始化成0.
④遍历顺序:因根据前面的值求的,所以从小到大遍历。
⑤最后返回dp[prices.length-1][1]
下面为代码(java):
2.题目链接:122. 买卖股票的最佳时机 II
题目描述:
给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
解法:
①此题在前面用贪心做过一次就不再介绍了,介绍dp解法。
②此题和上题的不同就在于,可以多次买卖股票,所以在递推公式上有所不同,但是别的地方都差不多。即dp[i][0]仍表示,在第i天持有股票的最大价值为dp[i][0];dp[i][1]仍表示,在第i天不持有股票的最大价值为dp[i][1].
③dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i]) --- 因为股票可以买卖多次,所以在上一天没买的情况下,我们要将上一天经历买卖后的最大价值加上。
dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i]);
④最后返回dp[nums.length-1][1] --- 因为最后一天一定是不持有股票的时候拥有最大利润。
下面为代码(java):
3.总结:
①两道股票问题,一个是只能买卖一次,一个是能买卖多次。
②用动态规划来解决总体思路差不多故dp含义一样,当前是否持有股票的最大利润都根据前面的值求,故初始化和遍历顺序一样的。
③但是递推公式不同,如果可以买卖多次的话再买的时候要加上前面已经买卖过的利润。
④用贪心也可以解决且效率更高,但是贪心只能解决特定的股票问题,而dp可以解决股票系列问题。