给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。
注意:你不能在买入股票前卖出股票。
解法一
暴力破解
class Solution {
public int maxProfit(int[] prices) {
//暴力破解
if (prices == null || prices.length < 2) return 0;
int max = 0;
for (int i = 0; i < prices.length - 1; i++) {
for (int j = i; j < prices.length; j++) {
max = Math.max(max, prices[j] - prices[i]);
}
}
return max;
}
}
解法二
贪心
class Solution {
public int maxProfit(int[] prices) {
//贪心
if (prices == null || prices.length < 2) return 0;
int minValue = Integer.MAX_VALUE; //维护一个最小值
int max = 0;
for (int i = 0; i < prices.length; i++) {
minValue = Math.min(minValue, prices[i]);
max = Math.max(max, prices[i] - minValue);
}
return max;
}
}
解法三
动态规划
class Solution {
public int maxProfit(int[] prices) {
//动态规划
if (prices == null || prices.length < 2) return 0;
//dp[][0]:买入
//dp[][1]:卖出
int[][] dp = new int[prices.length][2];
dp[0][0] = -prices[0]; //第一天买入
dp[0][1] = 0; //第一天卖出(因为直接卖出,所以收益为0(这里不考虑手续费))
//循环从第二天开始
for (int i = 1; i < prices.length; i++) {
//下面的前一天都是泛指,前一天不一定就是昨天,因为dp数组会继承最优的情况
//买入,和前一天比较,哪个买入价低用哪个(-prices[i]为今天的买入价,dp[i - 1][1]为前一天的买入价)
//前一天的买入价可能不是前一天买的,也可能是前前天,因为前一天和前前天比较后也会选择低的买入价继承
//因为是买入所以是负的,大的那个值就是买入价低
dp[i][0] = Math.max(-prices[i], dp[i - 1][0]);
//卖出,和前一天比较,哪个卖出价高用哪个
//dp[i - 1][0] + prices[i]:今天卖出的价格(前一天的买入价+今天的股价)
//dp[i - 1][1]:前一天卖出的价格
dp[i][1] = Math.max(dp[i - 1][0] + prices[i], dp[i - 1][1]);
}
//返回最后一天的卖出价(因为买入和卖出都会继承最优的情况,所以最后的都是最优的买入和卖出价)
return dp[dp.length - 1][1];
}
}
动态规划优化
class Solution {
public int maxProfit(int[] prices) {
//动态规划优化
//仔细观察上面的代码,是不是发现了每次循环的今天都只和前一天有关
//所以可以压缩dp数组的空间,从二维变为一维,只有买入和卖出
if (prices == null || prices.length < 2) return 0;
//dp[0]:买入
//dp[1]:卖出
int[] dp = new int[2];
//第一天的买入卖出
dp[0] = -prices[0];
dp[1] = 0;
//循环从第二天开始
for (int i = 1; i < prices.length; i++) {
//只是去掉前一个[],其他不变
dp[0] = Math.max(-prices[i], dp[0]);
dp[1] = Math.max(dp[0] + prices[i], dp[1]);
}
return dp[1];
}
}
思路学着题解区liweiwei1419
大佬和王尼玛
大佬。