Skip to content

Commit 92d04dc

Browse files
author
oushihao
committed
feat(best-time-to-buy-and-sell-stock-4): 动态规划
1 parent b6878f9 commit 92d04dc

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# 买卖股票的最佳时机 IV
2+
3+
> 难度:困难
4+
>
5+
> https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/
6+
7+
## 题目
8+
9+
给定一个整数数组  `prices` ,它的第 i 个元素  `prices[i]` 是一支给定的股票在第
10+
`i` 天的价格。
11+
12+
设计一个算法来计算你所能获取的最大利润。你最多可以完成 `k` 笔交易。
13+
14+
**注意** :你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
15+
16+
### 示例
17+
18+
#### 示例 1:
19+
20+
```
21+
输入:k = 2, prices = [2,4,1]
22+
输出:2
23+
解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
24+
```
25+
26+
#### 示例 2:
27+
28+
```
29+
输入:k = 2, prices = [3,2,6,5,0,3]
30+
输出:7
31+
解释:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
32+
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。
33+
```
34+
35+
## 解题
36+
37+
```typescript
38+
/**
39+
* 动态规划
40+
* @desc 时间复杂度 O(N min(N, k)) 空间复杂度 O(min(N, k))
41+
* @param k
42+
* @param prices
43+
*/
44+
export function maxProfit(k: number, prices: number[]): number {
45+
const len = prices.length;
46+
if (len === 0) return 0;
47+
48+
// k只能ken/2
49+
k = Math.min(k, len >> 1);
50+
51+
// 对于 prices[i] 中的价格而言,进行恰好 i 笔交易,并且当前手上持有一支股票,这种情况下的最大利润
52+
const buy: number[] = new Array(k + 1).fill(-Number.MAX_VALUE);
53+
buy[0] = -prices[0];
54+
55+
// 用 sell[i] 表示恰好进行 i 笔交易,并且当前手上不持有股票,这种情况下的最大利润
56+
const sell: number[] = new Array(k + 1).fill(0);
57+
58+
// 遍历所有天数
59+
for (let i = 1; i < len; i++) {
60+
// 更新第一次买入的价格
61+
buy[0] = Math.max(buy[0], sell[0] - prices[i]);
62+
// 遍历购买次数
63+
for (let j = 1; j <= k; j++) {
64+
// 更新第j次买入的价格
65+
buy[j] = Math.max(buy[j], sell[j] - prices[i]);
66+
// 更新第j次卖出的价格
67+
sell[j] = Math.max(sell[j], buy[j - 1] + prices[i]);
68+
}
69+
}
70+
71+
return Math.max(...sell);
72+
}
73+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { maxProfit } from '.';
2+
3+
describe('买卖股票的最佳时机 IV', () => {
4+
testCase(maxProfit);
5+
});
6+
7+
function testCase(fn: (k: number, prices: number[]) => number) {
8+
it('示例一', () => {
9+
const k = 2;
10+
const prices = [2, 4, 1];
11+
const expected = 2;
12+
expect(fn(k, prices)).toStrictEqual(expected);
13+
});
14+
15+
it('示例二', () => {
16+
const k = 2;
17+
const prices = [3, 2, 6, 5, 0, 3];
18+
const expected = 7;
19+
expect(fn(k, prices)).toStrictEqual(expected);
20+
});
21+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* 动态规划
3+
* @desc 时间复杂度 O(N min(N, k)) 空间复杂度 O(min(N, k))
4+
* @param k
5+
* @param prices
6+
*/
7+
export function maxProfit(k: number, prices: number[]): number {
8+
const len = prices.length;
9+
if (len === 0) return 0;
10+
11+
// k只能ken/2
12+
k = Math.min(k, len >> 1);
13+
14+
// 对于 prices[i] 中的价格而言,进行恰好 i 笔交易,并且当前手上持有一支股票,这种情况下的最大利润
15+
const buy: number[] = new Array(k + 1).fill(-Number.MAX_VALUE);
16+
buy[0] = -prices[0];
17+
18+
// 用 sell[i] 表示恰好进行 i 笔交易,并且当前手上不持有股票,这种情况下的最大利润
19+
const sell: number[] = new Array(k + 1).fill(0);
20+
21+
// 遍历所有天数
22+
for (let i = 1; i < len; i++) {
23+
// 更新第一次买入的价格
24+
buy[0] = Math.max(buy[0], sell[0] - prices[i]);
25+
// 遍历购买次数
26+
for (let j = 1; j <= k; j++) {
27+
// 更新第j次买入的价格
28+
buy[j] = Math.max(buy[j], sell[j] - prices[i]);
29+
// 更新第j次卖出的价格
30+
sell[j] = Math.max(sell[j], buy[j - 1] + prices[i]);
31+
}
32+
}
33+
34+
return Math.max(...sell);
35+
}

0 commit comments

Comments
 (0)