前言
动态规划专题,从简到难通关动态规划。
每日一题
今天的题目是 121. 买卖股票的最佳时机
给定一个数组 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 <= 1050 <= prices[i] <= 104
题解
暴⼒
这道题⽬最直观的想法,就是暴⼒,找最优间距了。
function maxProfit(prices: number[]): number {
let result = 0;
for (let i = 0; i < prices.length; i++) {
for (let j = i + 1; j < prices.length; j++) {
result = Math.max(result, prices[j] - prices[i]);
}
}
return result;
};
当然直接提交会造成超时
贪心
题目要求查找最大收益,根据贪心思想,只要在每次寻找的过程中记录下最小股价和最大收益,不断更新得到最终结果。具体的处理方法如下:
-
从第二天开始遍历股价数组,判断每一天是否是最小的股价,如果是,那么将它记录下来作为当前的买入价。
-
每一天都计算以当前股价卖出时的最大收益,并将这个最大收益和之前计算得到的最大收益做比较,如果当前的最大收益比之前的最大收益要大,那么记录下来作为新的最大收益。
-
最终返回最大收益。
function maxProfit(prices: number[]): number {
let minPrice = Infinity;
let maxProfit = 0;
for (let i = 0; i < prices.length; i++) {
if (prices[i] < minPrice) {
minPrice = prices[i];
} else if (prices[i] - minPrice > maxProfit) {
maxProfit = prices[i] - minPrice;
}
}
return maxProfit;
};
动态规划
- 定义 dp 数组
首先我们定义 dp 数组,其中 dp[i] 表示第 i 天卖出股票所能获得的最大利润。在第 i 天卖出股票意味着我们需要在 [0, i-1] 区间内选择一个价格最低的股票进行买入,才能产生最大利润。
- 确定递推公式
当我们遍历到第 i 天时,如果要在这一天卖出股票获得最大利润,那么必须在 [0, i-1] 区间内选择一个价格最低的股票进行买入。设这个最低价格为 minPrice,则当前卖出的最大利润为 prices[i] - minPrice。
但是,还需要考虑到,卖出股票获得最大利润是否是在前一天(也就是 i-1)卖出获得的利润更大,还是在当前这一天卖出获得的利润更大。因此我们需要比较两种情况,选择其中的较大值作为 dp[i] 的取值。
所以,得到递推公式:
dp[i] = max(dp[i-1], prices[i]-minPrice)
- 初始化dp数组
在本题中,我们可以将 dp[0] 的值赋为 0,即第 0 天不进行任何交易,所以利润为 0。后面的天数都初始化为0,方便后面赋值
- 确定遍历顺序
由递推公式可以得到,遍历顺序就是由第0天开始往后直到最后一天
代码:
function maxProfit(prices: number[]): number {
const n = prices.length;
if (n < 2) {
return 0;
}
const dp = new Array(n).fill(0);
let minPrice = prices[0];
for (let i = 1; i < n; i++) {
minPrice = Math.min(minPrice, prices[i - 1]);
dp[i] = Math.max(dp[i - 1], prices[i] - minPrice);
}
return dp[n - 1];
};