一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情。
前言
每天一道算法题,死磕算法
题目
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
分析
动态规划的题目我们依然用我们分析动态规划的方法去学习
最近做了一些动态规划的题目,总结了一下模板
- 1.定义新数组
动态规划题目一般需要定义一个新数组
let a=[]或let a=[][]之类的
我们的这个题目找出会变化的东西,然后用他们组成一个式子
会变化的东西如下:天数,利润,是否持有股票
就可以得到一个式子a[天数][是否持有]=利润
比如a[0][0]=0为,第一天,没有持有,利润为0
再比如a[0][1]=-7为,第一天,有持有,利润为-7
- 2.找到最简单的子问题
这个子问题一般都是
a[0],a[1]之类的,不可再分解的,这个其实就是递归的边界条件
a[0][0]=0;
a[0][1]=-7;
- 3.找到父问题
要能看出来让你求什么,一般也就是数组的第几个值
a[1][0] = Math.max(a[0][0],a[0][1]+今天价格]);
就是我第二天没有持有,取是第一天没有持有利润大还是今天卖了利润大
a[1][1] = Math.max(a[0][1],-今天价格)
就是我第二天持有,取是第一天的价格高还是今天的价格高,也就是你的持有成本
- 4.找到如何把父问题化成子问题(自顶向下推理不出来,就自底向上推理试试)
根据题目中的条件,想一下子问题是如何构成父问题的,这是最关键的一步,也是最难的一步,这个只能多做
这个就直接for循环就可以了,求出每一个数组的值
题解
function maxProfit(prices: number[]): number {
let length = prices.length;
let a = new Array(length); //表格有length行
for(var i = 0;i < a.length; i++){
a[i] = new Array(2).fill(0); //每行有2列
}
a[0][0] = 0;
a[0][1] = -prices[0];
for(let i=1;i<prices.length;i++){
a[i][0] = Math.max(a[i-1][0],a[i-1][1]+prices[i]);
a[i][1] = Math.max(a[i-1][1],prices[i] + a[i-1][1]);
}
return a[length-1][0];
};