买卖股票的最佳时机II

LeetCode每日一题,122. Best Time to Buy and Sell Stock II

先看题目描述

BzBlrQ.png

大意就是给定一个列表代表股票每天的价格,规定只能多次买卖一支股票,再次购买前必须出售掉当前股票,让我们求可以获取的最大利润

算法和思路

动态规划

  • 状态定义:dp[i][j] 表示到下标为 i 的这一天,持股状态为 j 时,手上拥有的最大现金数,j = 0 时表示持有现金,j = 1 时表示持有股票
  • 状态转移方程: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]}

最后返回 dp[len - 1][0] 即可

贪心算法

贪心策略:由于不限制交易次数,只要今天股价比昨天高,就交易

这道题 「贪心」 的地方在于,对于 「今天的股价 - 昨天的股价」,得到的结果有 3 种可能:① 正数,② 0,③负数。贪心算法的决策是: 只加正数

算法源码

动态规划

未优化空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.*;

class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
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], dp[i - 1][0] - prices[i]);
}
return dp[len - 1][0];
}
}

由于当前状态的转移仅与上一个状态有关,可以采用类似滚动数组的方式进行状态转移,从而优化空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
int[][] dp = new int[len][2];
int preCash = 0;
int preStock = -prices[0];
int cash = 0;
int stock = 0;
for (int i = 1; i < len; i++) {
cash = Math.max(preCash, preStock + prices[i]);
stock = Math.max(preStock, preCash - prices[i]);
preCash = cash;
preStock = stock;
}
return cash;
}
}

贪心算法

只要有钱赚时,就卖出股票

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public int maxProfit(int[] prices) {
int res = 0;
for(int i = 1; i < prices.length; i++) {
if (prices[i] > prices[i-1]) {
//解题思路:贪心算法,只要有钱赚,就出售
res += prices[i] - prices[i-1];
}
}
return res;
}
}