持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情
题目:给定一个整数数组prices,其中prices[i]表示第i天股票的价格,现规定每次股票卖出都需要付出fee的手续费,并且同时不能持有两股股票,可进行多次买入卖出,问最终最大利润。
解题思路
本题还是解决股票买入卖出问题,之前做过只限定一天买入一天卖出,当时可采用动态规划找到最便宜和最贵的两天,进行相减即为正确答案。之后又出现了可多次买入卖出的股票题,当时每天都可以买入卖出,和本题的区别只是本题包含手续费。
而那题的解题思路也是动态规划,我们可以假定每天到底是买入还是卖出,假定是买入,则前一天必然不能买入,同理,如果前一天买入则当天也不能买入,当天的利润就等于前一天没有买入的利润减去当天的价格和前一天买入的利润和前一天买入的利润的最大值。而当天没有买入的利润就等于前一天没有买入的利润和前一天买入的利润加上当天买入的价格的最大值。
之后根据动态规划就能得出最终的结果,但此时如果加上利润我们则需在上述表达式中进行修改,此时需要注意的是在何时将手续费扣除,那理论上是在卖出时扣除,但上面的表述并没有卖出,其实不买入的意思就是卖出,因为一天持有股票的状态限定只有买入和卖出。可的代码如下:
public int maxProfit(int[] prices, int fee) {
int[][] dp = new int[prices.length][2];
dp[0][0] = -prices[0];
dp[0][1] = 0;
for(int i=1;i<prices.length;i++){
dp[i][0] = Math.max(dp[i-1][1]-prices[i], dp[i-1][0]);
dp[i][1] = Math.max(dp[i-1][0]+prices[i]-fee, dp[i-1][1]);
}
return dp[prices.length-1][1];
}
当然还有一种思路是贪心算法:
我们限定一个标准,我们初始时票价位price[0]加上手续费,只有之后的价格大于此价格的时候才选择卖出,否则如果中途遇到手续费加价格小于当前的,就更新当前价格,以此类推,最终可得到代码:
public int maxProfit2(int[] prices, int fee) {
int profit = 0;
int buy = prices[0] + fee;
for (int price : prices) {
if(price + fee <buy){
buy = price + fee;
}else if(price > buy) {
profit += price - buy;
buy = price;
}
}
return profit;
}