本人已迁移博客至掘进,以后会在掘进平台更新最新的文章也会有更多的干货,欢迎大家关注!!!https://juejin.im/user/588993965333309
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出:5解释: 在第2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5。
注意利润不能是7-1 = 6, 因为卖出价格需要大于买入价格。
示例2:
输入: [7,6,4,3,1]
输出:0解释: 在这种情况下, 没有交易完成, 所以最大利润为0。
解法一: 暴力解决法
算法思想:
我们需要找出给定数组中两个数字之间的最大差值(即,最大利润)。此外,第二个数字(卖出价格)必须大于第一个数字(买入价格)。
对于每组 i 和 j (j > i)我们需要找出max(prices[j] - prices[i])
代码如下:
func maxProfit(_ prices: [Int]) ->Int {
guard prices.count> 0 else {return 0}
var maxProfit: Int= 0
for i in 0..
maxProfit= max(maxProfit, prices[j] -prices[i])
}
}returnmaxProfit
}
解法二:动态规划
算法思想:
动态规划的3个步骤:
设定状态
推导方程
起始值和输出
这里状态的设置得稍微想一想,数组的问题一般我们得固定其中一个变量。这道题有两个变量,一个是“买入”,另一个是“卖出”,这里我们固定“卖出”变量,“买入”变量一定在它之前。
因此状态dp[i]表示:在索引为 i 的这一天,用户所能获得的最大利润。
下面思考状态转移,我们就要想dp [i] 的从前面的状态值转移过来,但是我们就会发现新的问题dp[i - 1]、dp[i - 2]、……、dp[0],状态转移无从下手。这里就说明:状态还不够,得把“买入”和“卖出”操作加入到状态的设置中。
于是下面修改状态的定义:
dp[i][0]表示:在索引为 i 的这一天,用户手上不持股所能获得的最大利润;
1、 0 一般表示没有,在索引为 i 的这一天,手上没有股票,语义上也是清晰的,下面对状态 1的理解也是一样;2、 “用户手上不持股”不代表用户一定在索引为 i 的这一天把股票抛售了;3、 在索引为 i 的这一天具体应该这样理解:从索引为 0 的天数开始,到索引为 i 的这一天,因此,这个状态的设置具有“前缀”的意味,因此输出是 dp[len - 1][0],不可能是 dp[len - 1][1],在只发生一次交易的情况下,持有这支股票一定不能使我们获得最大利润。
状态dp[i][1]表示:在索引为 i 的这一天,用户手上持股所能获得最大的利润。
下面考虑状态转移方程:
dp[i][0] 可以由谁转移过来?
dp[i - 1][0] :今天不持股,假设我今天什么都不操作,当然可以从昨天不持股转移过来,这一点是显然的
dp[i - 1][1] + prices[i]:昨天持股,就在索引为 i 的这一天,我卖出了股票,状态由 1 变成了 0,此时获得利润,因此加上这一天的股价。
综上:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
2. dp[i][1] 可以由谁转移过来?
dp[i - 1][1] :今天持股,假设我今天什么都不操作,当然可以从昨天持股转移过来,这一点是显然的;
-prices[i]:**请注意:**状态 1 不能由状态 0 来,因为事实上,状态 0 特指:“卖出股票以后不持有股票的状态”,请注意这个状态和“没有进行过任何一次交易的不持有股票的状态”的区别。
因此,-prices[i] 就表示,在索引为 i 的这一天,执行买入操作得到的收益,再次强调:因为题目只允许一次交易,因此不能加上 dp[i - 1][0]。
综上:dp[i][1] = max(dp[i - 1][1], -prices[i]);
在新修改的定义中,我们已经分析出了输出dp[len - 1][0]
public int maxProfit(int[] prices) {int len =prices.length;if (len < 2) {return 0;
}//0:用户手上不持股所能获得的最大利润,特指卖出股票以后的不持股,非指没有进行过任何交易的不持股//1:用户手上持股所能获得的最大利润//注意:因为题目限制只能交易一次,因此状态只可能从 1 到 0,不可能从 0 到 1//状态转移方程://dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])//dp[i][1] = max(dp[i - 1][1], -prices[i])
int[][] dp = new int[len][2];
dp[0][0] = 0;
dp[0][1] = -prices[0];for (int i = 1; i < len; 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], -prices[i]);
}return dp[len - 1][0];
}
以上就是股票最大收益算法,希望对大家有所帮助!!!