1.题目描述:
给定一个数组prices,它的第i个元素prices[i]表示一支给定股票第i天的价格。你只能选择某一天买入这只股票,并选择在未来的某一个不同的日子卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回0。
2.暴力解法:
双层for循环,超时。
class Solution {
public int maxProfit(int[] prices) {
int max = 0;
for (int i = 0; i < prices.length; i++) {
for (int j = i + 1; j < prices.length; j++) {
max = Math.max(max, prices[j] - prices[i]);
}
}
return max;
}
}
3.贪心算法:
一次遍历同时记录最小值和差值最大值。
class Solution {
public int maxProfit(int[] prices) {
int min = Integer.MAX_VALUE;
int max = 0;
for (int i = 0; i < prices.length; i++) {
min = Math.min(min, prices[i]);
max = Math.max(max, prices[i] - min);
}
return max;
}
}
4.动态规划:
关键在于二维dp数组的定义和推导,详见代码:
class Solution {
public int maxProfit(int[] prices) {
if (prices.length == 1) return 0;
int[][] dp = new int[prices.length][2];
//dp[i][0]代表持有股票,dp[i][1]代表不持有股票手里的钱
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][0], -prices[i]);//i-1就持有股票和i买入
dp[i][1] = Math.max(dp[i - 1][1], dp[i][0] + prices[i]);//i-1就不持有股票和i卖出
}
return dp[prices.length - 1][1];
}
}
状态压缩:
class Solution {
public int maxProfit(int[] prices) {
if (prices.length == 1) return 0;
int[][] dp = new int[2][2];
dp[0][0] = -prices[0];
dp[0][1] = 0;
for (int i = 1; i < prices.length; i++) {
dp[i % 2][0] = Math.max(dp[(i - 1) % 2][0], -prices[i]);
dp[i % 2][1] = Math.max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);
}
return dp[(prices.length - 1) % 2][1];
}
}