一、leetcode题目
今天leetcode的题目刷的多,蓝桥的就没刷。
1.买卖股票的最佳时机 IV
题目描述
给定一个整数数组 prices
,它的第 i
个元素 prices[i]
是一支给定的股票在第 i
天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 k
笔交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
(1)测试用例
输入:
k = 2, prices = [3,2,6,5,0,3]
输出:
7
解释:
在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。
提示
- 0 <= k <= 100
- 0 <= prices.length <= 1000
- 0 <= prices[i] <= 1000
(2)思路
与买卖股票的最佳时机3类似,买卖股票3是只限制购买两次,这题限制购买次数为K
次,之前限制购买两次需要4个状态来进行表示,这题所以需要2 * k
个状态来进行表示。
(3)算法实现
class Solution {
public int maxProfit(int k, int[] prices) {
int len = prices.length;
// int[][] dp = new int[len][2 * k + 1];
// dp数组方面我直接使用了状态压缩,就不需要定义dp数组为二维数组。
int[] dp = new int[2 * k + 1];
for(int i = 0; i < 2 * k; i += 2){
dp[i+1] = -prices[0];
}
for(int i = 1; i < len; i++){
for(int j = 0; j < 2 * k; j += 2){
dp[j+1] = Math.max(dp[j+1], dp[j] - prices[i]);
dp[j+2] = Math.max(dp[j+2], dp[j+1] + prices[i]);
}
}
return dp[2*k];
}
}
2.买卖股票的最佳时机含手续费
题目描述
给定一个整数数组 prices
,其中 prices[i]
表示第 i
天的股票价格 ;整数 fee
代表了交易股票的手续费用。
你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。
返回获得利润的最大值。
注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
(1)测试用例
输入:
prices = [1, 3, 2, 8, 4, 9], fee = 2
输出:
8
解释:
能够达到的最大利润:
在此处买入 prices[0] = 1
在此处卖出 prices[3] = 8
在此处买入 prices[4] = 4
在此处卖出 prices[5] = 9
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8
提示
- 1 < = p r i c e s . l e n g t h < = 5 ∗ 1 0 4 1 <= prices.length <= 5 * 10^4 1<=prices.length<=5∗104
- 1 < = p r i c e s [ i ] < 5 ∗ 1 0 4 1 <= prices[i] < 5 * 10^4 1<=prices[i]<5∗104
- 0 < = f e e < 5 ∗ 1 0 4 0 <= fee < 5 * 10^4 0<=fee<5∗104
(2)思路
本体不限制购买次数,起始与买卖购票的最佳时机2差别不大,只是在一次买入卖出操作后扣除手续费。那么直接在一次买入卖出交易完成时,直接拿最大价值减去手续费即可。
(3)算法实现
class Solution {
public int maxProfit(int[] prices, int fee) {
int len = prices.length;
int[] dp = new int[2];
dp[0] = -prices[0];
for(int i = 1; i < len; i++){
// 其实设置一个中间变量较为合适,因为dp[1]根据dp[0]的状态发生变化
// 在dp[1]进行状态转移时,dp[0]已经发生变化,不够本题添不添加不影响最终结果,所以没添加。
dp[0] = Math.max(dp[0], dp[1]-prices[i]);
dp[1] = Math.max(dp[1], dp[0]+prices[i]-fee);
}
return dp[1];
}
}
3.最佳买卖股票时机含冷冻期
题目描述
给定一个整数数组prices
,其中第 prices[i]
表示第 i
天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1
天)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
(1)测试用例
输入:
prices = [1,2,3,0,2]
输出:
3
解释:
对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
提示
- 1 <= prices.length <= 5000
- 0 <= prices[i] <= 1000
(2)思路
还是在买卖购票的最佳时机2添加的一些限制操作,可以无限次的买入卖出,但是有冷冻期。为此,我们的dp数组可以再添加一个状态,使其拥有四个状态:
- dp[i][0] 不任何进行操作
- dp[i][1]: 在第i个阶段进行买入操作
- dp[i][2]: 在第i个阶段进行卖出操作
- dp[i][3]: 第i个阶段能够进行买入的等待状态。
- 状态转移方程式:
- dp[i][1] = max(dp[i-1][1], dp[i-1][3] - prices[i]);(买入状态只能在冷冻期或在可以买入的状态才行,一定不是能刚卖出的状态)
- dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i]);
- dp[i][3] = dp[i-1][2];
- 边界条件:
dp[0][1] = -prices[0];
(3)算法实现
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
int[] dp = new int[4];
dp[1] = -prices[0];
for(int i = 1; i < len; i++){
dp[1] = Math.max(dp[1], dp[3] -prices[i]);
// 因为状态压缩的dp[2] 会在dp[3]之前发生变化,所以dp[3]的状态转移一定得在dp[2]之前。
dp[3] = dp[2];
dp[2] = Math.max(dp[2], dp[1] +prices[i]);
}
return Math.max(dp[3], dp[2]);
}
}