day41 买卖股票

day41 买卖股票
### 9.25 121. Best Time to Buy and Sell Stock
You are given an array prices where prices`[i] is the price of a given stock on the ith day.
You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.
Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/description/
121. 买卖股票的最佳时机 
https://www.bilibili.com/video/BV1Xe4y1u77q
https://programmercarl.com/0121.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BA.html

dp`[i] : 第i天获利最大的情况
dp`[0] = 0;
dp`[1] = Math.max(dp[0], )
自己写碰到的问题:dp数组递推公式不会写,dp数组含义也不明

dp`[i][0]: 持有股票获得的最大利润
dp`[i][1]: 不持有股票获得的最大利润

dp`[i][0]:
分为两种情况:
1. 第i天买入了股票: -price`[i]
2. 前一天就已经持有了,第i天继续持有 dp`[i-1][0]
dp`[i][1]: 
分为两种情况:
1. 第i天卖了股票:dp`[i-1][0] + price[i]
2. 前一天已经卖掉了:  dp`[i-1][0]

```java
public class stock121 {  
    public int maxProfit(int[] prices) {  
        //if(prices.length == 1) return 0;  
  
        int[][] dp = new int[prices.length][2];  
        dp[0][0] = -prices[0];//hold  
        dp[0][1] = 0;//notHolding  
  
        for (int i = 1; i < prices.length; i++) {  
            dp[i][0] = Math.max(dp[i-1][0], -prices[i]);  
            dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0]+prices[i]);  
            System.out.println("dp["+ i + "][0] = " + dp[i][0]);  
            System.out.println("dp["+ i + "][1] = " + dp[i][1]);  
        }  
  
        return Math.max(dp[prices.length-1][0],dp[prices.length-1][1]);  
  
    }  
}  
class stock121Test {  
    public static void main(String[] args) {  
        stock121 example = new stock121();  
        int[] prices = {7};  
        System.out.println(example.maxProfit(prices));  
  
  
    }  
}
```

### 9.26 122. Best Time to Buy and Sell Stock II
You are given an integer array prices where prices`[i] is the price of a given stock on the ith day.
On each day, you may decide to buy and/or sell the stock. You can only hold at most one share of the stock at any time. However, you can buy it then immediately sell it on the same day.
Find and return the maximum profit you can achieve.
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/

 122.买卖股票的最佳时机II  
https://www.bilibili.com/video/BV1D24y1Q7Ls
https://programmercarl.com/0122.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BAII%EF%BC%88%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%EF%BC%89.html  

之前用贪心算法解过这个题,即负数就不考虑,正数就加上。

动态规划是另一种思路。
dp`[i][0] :持有股票获得的最大利润
和一次买卖的区别:不一定是第一次购买,手上的现金不一定是0
dp`[i][1] :不持有股票获得的最大利润

```java
public class stock122 {  
    public int maxProfit(int[] prices) {  
        int[][] dp = new int[prices.length][2];  
        dp[0][0] = -prices[0];//unhold  
        dp[0][1] = 0;//holding  
  
        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 Math.max(dp[prices.length-1][0],dp[prices.length-1][1]);  
    }  
}  
class stock122Test {  
    public static void main(String[] args) {  
        stock122 example = new stock122();  
        int[] prices = {1};  
        System.out.println(example.maxProfit(prices));  
    }  
}
```
### 9.27 123. Best Time to Buy and Sell Stock III
You are given an array prices where prices`[i] is the price of a given stock on the ith day.
Find the maximum profit you can achieve. You may complete at most two transactions.
Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/description/

 123.买卖股票的最佳时机III  
这道题一下子就难度上来了,关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。
https://www.bilibili.com/video/BV1WG411K7AR

https://programmercarl.com/0123.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BAIII.html

dp`[i][0]: 从未操作过
dp`[i][1]:第一次持有
dp`[i][2]:第一次不持有
dp`[i][3]:第二次持有
dp`[i][4]:第二次不持有

dp`[i][0] = dp[i-1][0];
dp`[i][1] = Math.max( (dp[i-1][0] - prices[i]), dp[i-1][1] );
//怎么判断是第一次不持有?但从dp`[i-1][0]看不出来。
//答:dp`[i-1][2]即可延续前一天第一次不持有的状态
dp`[i][2] = Math.max(dp[i-1][1] + prices[i] , dp[i-1][2])
dp`[i][3] = Math.max(dp[i-1][2] - prices[i], dp[i-1][3])
dp`[i][4] = Math.max(dp[i-1][3] + prices[i], dp[i-1][4])

>[!Tips]
>自己写的时候碰到的问题:当int[] prices = {1, 2, 3, 4, 5};时,
>prices[1] = 2   
dp[1][0] = 0   dp[1][1] = -1   dp[1][2] = 1   dp[1][3] = 0   dp[1][4] = 2
prices[2] = 3   
dp[2][0] = 0   dp[2][1] = -1   dp[2][2] = 2   dp[2][3] = 0   dp[2][4] = 3
prices[3] = 4   
dp[3][0] = 0   dp[3][1] = -1   dp[3][2] = 3   dp[3][3] = 0   dp[3][4] = 4
prices[4] = 5   
dp[4][0] = 0   dp[4][1] = -1   dp[4][2] = 4   dp[4][3] = 0   dp[4][4] = 5
>最后一天的时候直接0+5=5了。但此时手上没有股票,卖不了
>这是初始化错误导致的。dp[0][3] 应初始化为 -prices[0]; 而不是0。 因为这是持有的状态。

```java
public class stock123 {  
    public int maxProfit(int[] prices) {  
        int[][] dp = new int[prices.length][5];  
        dp[0][0] = 0;  
        dp[0][1] = -prices[0];  
        dp[0][2] = 0;  
        dp[0][3] = -prices[0];  
        dp[0][4] = 0;  
  
        for (int i = 1; i < prices.length; i++) {  
            dp[i][0] = dp[i - 1][0];  
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);  
            dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1] + prices[i]);  
            dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]);  
            dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]);  
            System.out.println("prices[" + i + "] = " + prices[i] + "   ");  
            System.out.print("dp[" + i + "][0] = " + dp[i][0] + "   ");  
            System.out.print("dp[" + i + "][1] = " + dp[i][1] + "   ");  
            System.out.print("dp[" + i + "][2] = " + dp[i][2] + "   ");  
            System.out.print("dp[" + i + "][3] = " + dp[i][3] + "   ");  
            System.out.println("dp[" + i + "][4] = " + dp[i][4]);  
  
        }   
  
        return dp[prices.length - 1][4];  
        //现在最大的时候一定是卖出的状态,而两次卖出的状态现金最大一定是最后一次卖出。如果想不明白的录友也可以这么理解:如果第一次卖出已经是最大值了,那么我们可以在当天立刻买入再立刻卖出。所以dp[4][4]已经包含了dp[4][2]的情况。也就是说第二次卖出手里所剩的钱一定是最多的。
  
    }  
}  
  
class stock123Test {  
    public static void main(String[] args) {  
        stock123 example = new stock123();  
        int[] prices = {1, 2, 3, 4, 5};  
        System.out.println(example.maxProfit(prices));  
    }  
}
```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值