---
# System prepended metadata

title: 121. Best Time to Buy and Sell Stock
tags: [Leetcode, Dynamic Programming, Easy]

---

# 121. Best Time to Buy and Sell Stock
###### tags: `Leetcode` `Easy` `Dynamic Programming`
Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
## 思路
### 思路一 暴力解法（超时）
双层回圈 算出每两个数的差 找出最大值
### 思路二 DP（超时）
一开始被dp困住了...认准它要用dp解
dp表格 **如果题目要求最大值，并不一定是每个格子都存最大值~**
于是用了一个nums.length*numslength的array，对角线下面都是0, dp[i][j]代表在第i天及以后买入，在第j天及以前卖掉的最大利润
也就是```    dp[i][j] = max(dp[i][j-1],dp[i-1][j], nums[j]-nums[i])```
### 思路三

我们来假设自己来购买股票。随着时间的推移，每天我们都可以选择出售股票与否。那么，假设在第 i 天，如果我们要在今天卖股票，那么我们能赚多少钱呢？

显然，如果我们真的在买卖股票，我们肯定会想：如果我是在历史最低点买的股票就好了！太好了，在题目中，我们只要用一个变量记录一个历史最低价格 minprice，我们就可以假设自己的股票是在那天买的。那么我们在第 i 天卖出股票能得到的利润就是 prices[i] - minprice。

因此，我们只需要遍历价格数组一遍，记录历史最低点，然后在每一天考虑这么一个问题：如果我是在历史最低点买进的，那么我今天卖出能赚多少钱？当考虑完所有天数之时，我们就得到了最好的答案。

**另一种理解**
可以看做一种动态规划，只不过对空间复杂度进行了优化。考虑每次如何获取最大收益？第i天的最大收益只需要知道前i天的最低点就可以算出来了。而第i天以前（包括第i天）的最低点和i-1天的最低点有关，至此我们的动态方程就出来了。

dp[i] = min(d[i-1],prices[i])
其中dp[0]=prices[0],然后动态计算之后的就可以了。 得到了前i天的最低点以后，只需要维护一个max用来保存最大收益就可以了。 这个时候是空间复杂度O（n）的动态规划
接着考虑优化空间，仔细观察动态规划的辅助数组，其每一次只用到了dp[-1]这一个空间，因此可以把数组改成单个变量dp来存储截止到第i天的价格最低点。
## Code
### 思路一
```java=
public class Solution {
    public int maxProfit(int prices[]) {
        int maxprofit = 0;
        for (int i = 0; i < prices.length - 1; i++) {
            for (int j = i + 1; j < prices.length; j++) {
                int profit = prices[j] - prices[i];
                if (profit > maxprofit)
                    maxprofit = profit;
            }
        }
        return maxprofit;
    }
}
```
### 思路二
```java=
class Solution {
    public int maxProfit(int[] prices) {
        int [] dp = new int[prices.length];
        for(int i = 0;i < prices.length-1;i++){
            for(int j = i+1;j < prices.length;j++){
                dp[j] = Math.max(Math.max(prices[j]-prices[i], dp[j]),dp[j-1]);
            }
        }
        return dp[prices.length-1];
    }
}
```
### 思路三
```java=
public class Solution {
    public int maxProfit(int prices[]) {
        int minPoint = prices[0];
        int maxProfit = 0;
        for(int price:prices){
            if(minPoint > price){
                minPoint = price;
            }
            if(price-minPoint>maxProfit){
                maxProfit = price-minPoint;
            }
        }
        return maxProfit;
    }
}
```
## Result
### 思路三
Runtime: 3 ms, faster than **24.34%** of Java online submissions for Best Time to Buy and Sell Stock.
Memory Usage: 105.6 MB, less than **9.00%** of Java online submissions for Best Time to Buy and Sell Stock.