参与本项目 ,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们受益! 714.买卖股票的最佳时机含手续费 力扣题目链接 给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。 你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。 返回获得利润的最大值。 注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们受益!
给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。
你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。
返回获得利润的最大值。
注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
示例 1:
解释: 能够达到的最大利润:
注意:
《代码随想录》算法视频公开课:,相信结合视频再看本篇题解,更有助于大家对本题的理解。
本题贪心解法:贪心算法:买卖股票的最佳时机含手续费
性能是:
本题使用贪心算法并不好理解,也很容易出错,那么我们再来看看使用动规的方法如何解题。
相对于动态规划:122.买卖股票的最佳时机II,本题只需要在计算卖出操作的时候减去手续费就可以了,代码几乎是一样的。
唯一差别在于递推公式部分,所以本篇也就不按照动规五部曲详细讲解了,主要讲解一下递推公式部分。
这里重申一下dp数组的含义:
dp[i][0] 表示第i天持有股票所得最多现金。
dp[i][1] 表示第i天不持有股票所得最多现金
如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来
所以:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
在来看看如果第i天不持有股票即dp[i][1]的情况, 依然可以由两个状态推出来
所以:dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);
本题和动态规划:122.买卖股票的最佳时机II的区别就是这里需要多一个减去手续费的操作。
以上分析完毕,C++代码如下:
class Solution { public: int maxProfit(vector<int>& prices, int fee) { int n = prices.size(); vector<vector<int>> dp(n, vector<int>(2, 0)); dp[0][0] -= prices[0]; // 持股票 for (int i = 1; i < n; i++) { dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]); dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee); } return max(dp[n - 1][0], dp[n - 1][1]); } };
/** * 卖出时支付手续费 * @param prices * @param fee * @return */ public int maxProfit(int[] prices, int fee) { int len = prices.length; // 0 : 持股(买入) // 1 : 不持股(售出) // dp 定义第i天持股/不持股 所得最多现金 int[][] dp = new int[len][2]; dp[0][0] = -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][0] + prices[i] - fee, dp[i - 1][1]); } return Math.max(dp[len - 1][0], dp[len - 1][1]); } /** * 买入时支付手续费 * @param prices * @param fee * @return */ public int maxProfit(int[] prices, int fee) { int len = prices.length; // 0 : 持股(买入) // 1 : 不持股(售出) // dp 定义第i天持股/不持股 所得最多现金 int[][] dp = new int[len][2]; // 考虑买入的时候就支付手续费 dp[0][0] = -prices[0] - fee; for (int i = 1; i < len; i++) { dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i] - fee); dp[i][1] = Math.max(dp[i - 1][0] + prices[i], dp[i - 1][1]); } return Math.max(dp[len - 1][0], dp[len - 1][1]); } // 一维数组优化 class Solution { public int maxProfit(int[] prices, int fee) { int[] dp = new int[2]; dp[0] = -prices[0]; dp[1] = 0; for (int i = 1; i <= prices.length; i++) { dp[0] = Math.max(dp[0], dp[1] - prices[i - 1]); dp[1] = Math.max(dp[1], dp[0] + prices[i - 1] - fee); } return dp[1]; } } ```Java //使用 2*2 array class Solution { public int maxProfit(int[] prices, int fee) { int dp[][] = new int[2][2]; int len = prices.length; //[i][0] = holding the stock //[i][1] = not holding the stock dp[0][0] = -prices[0]; for(int i = 1; i < len; i++){ dp[i % 2][0] = Math.max(dp[(i - 1) % 2][0], dp[(i - 1) % 2][1] - prices[i]); dp[i % 2][1] = Math.max(dp[(i - 1) % 2][1], dp[(i - 1) % 2][0] + prices[i] - fee); } return dp[(len - 1) % 2][1]; } }
class Solution: def maxProfit(self, prices: List[int], fee: int) -> int: n = len(prices) dp = [[0] * 2 for _ in range(n)] dp[0][0] = -prices[0] #持股票 for i in range(1, n): dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i]) dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i] - fee) return max(dp[-1][0], dp[-1][1])
class Solution: def maxProfit(self, prices: List[int], fee: int) -> int: # 持有股票手上的最大現金 hold = -prices[0] - fee # 不持有股票手上的最大現金 not_hold = 0 for price in prices[1:]: new_hold = max(hold, not_hold - price - fee) new_not_hold = max(not_hold, hold + price) hold, not_hold = new_hold, new_not_hold return not_hold
// 买卖股票的最佳时机含手续费 动态规划 // 时间复杂度O(n) 空间复杂度O(n) func maxProfit(prices []int, fee int) int { n := len(prices) dp := make([][2]int, n) dp[0][0] = -prices[0] for i := 1; i < n; i++ { dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i] - fee) dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i]) } return dp[n-1][1] } func max(a, b int) int { if a > b { return a } return b }
const maxProfit = (prices,fee) => { let dp = Array.from(Array(prices.length), () => Array(2).fill(0)); dp[0][0] = 0 - prices[0]; for (let i = 1; i < prices.length; i++) { dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i]); dp[i][1] = Math.max(dp[i - 1][0] + prices[i] - fee, dp[i - 1][1]); } return Math.max(dp[prices.length - 1][0], dp[prices.length - 1][1]); }
function maxProfit(prices: number[], fee: number): number { /** dp[i][0]:持有股票 dp[i][1]: 不持有 */ const length: number = prices.length; if (length === 0) return 0; const dp: number[][] = new Array(length).fill(0).map(_ => []); dp[0][0] = -prices[0]; dp[0][1] = 0; for (let i = 1; i < length; 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], dp[i - 1][0] + prices[i] - fee); } return dp[length - 1][1]; };
#define max(a, b) ((a) > (b) ? (a) : (b)) // dp[i][0] 表示第i天持有股票所省最多现金。 // dp[i][1] 表示第i天不持有股票所得最多现金 int maxProfit(int* prices, int pricesSize, int fee) { int dp[pricesSize][2]; dp[0][0] = -prices[0]; dp[0][1] = 0; for (int i = 1; i < pricesSize; ++i) { dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]); dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee); } return dp[pricesSize - 1][1]; }
贪心
impl Solution { pub fn max_profit(prices: Vec<i32>, fee: i32) -> i32 { let mut result = 0; let mut min_price = prices[0]; for i in 1..prices.len() { if prices[i] < min_price { min_price = prices[i]; } // if prices[i] >= min_price && prices[i] <= min_price + fee { continue; } if prices[i] > min_price + fee { result += prices[i] - min_price - fee; min_price = prices[i] - fee; } } result } }
动态规划
impl Solution { pub fn max_profit(prices: Vec<i32>, fee: i32) -> i32 { let mut dp = vec![vec![0; 2]; prices.len()]; dp[0][0] = -prices[0]; for (i, &p) in prices.iter().enumerate().skip(1) { dp[i][0] = dp[i - 1][0].max(dp[i - 1][1] - p); dp[i][1] = dp[i - 1][1].max(dp[i - 1][0] + p - fee); } dp[prices.len() - 1][1] } }
动态规划空间优化
impl Solution { pub fn max_profit(prices: Vec<i32>, fee: i32) -> i32 { let (mut low, mut res) = (-prices[0], 0); for p in prices { low = low.max(res - p); res = res.max(p + low - fee); } res } }