参考资料:
题目描述:
给定一个数组 prices
,它的第 i
个元素 prices[i]
表示一支给定股票第 i
天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0
。
示例 1:
输入:[7,1,5,3,6,4] 输出:5 解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
思路分析:
dp[i][0]:第i天不持有这个股票所得的最多现金
dp[i][1]:第i天持有这个股票所得的最多现金
代码实现:
class Solution {
// //一次遍历,参考题解
// public int maxProfit(int[] prices) {
// //一次遍历,找最小值和min后面的max
// int len=prices.length;
// if(len==0) return 0;
// int minp=Integer.MAX_VALUE;
// int res=0;
// for(int i=0;i<len;i++){
// if(prices[i]<minp) minp=prices[i];
// else{//后面有比minp大的,可以考虑出手
// if(prices[i]-minp>res){
// res=prices[i]-minp;
// }
// }
// }
// return res;
// }
//动规
//只能持有一个股票
//dp[i][0]:第i天不持有这个股票所得的最多现金
//dp[i][1]:第i天持有这个股票所得的最多西现金
public int maxProfit(int[] prices) {
int n=prices.length;
int[][] dp=new int[n][2];
dp[0][0]=0;
dp[0][1]=-prices[0];
for(int i=1;i<n;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],-prices[i]);
}
return dp[n-1][0];
}
}
题目描述:
给你一个整数数组 prices
,其中 prices[i]
表示某支股票第 i
天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
示例 1:
输入:prices = [7,1,5,3,6,4] 输出:7 解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。 最大总利润为 4 + 3 = 7 。
思路分析:
由于可以多次买卖,所以dp[i][1],第i天持有这个股票的现金时,若第i天购入也不一定代表是第一次购入,所以dp[i][1]要改。
代码实现:
class Solution {
//差分数组
// public int maxProfit(int[] prices) {
// //可以理解为:最大的盈利就是将所有正值相加
// int len=prices.length;
// if(len==0 || len==1) return 0;
// int[] diff=new int[len];
// diff[0]=prices[0];
// for(int i=1;i<len;i++){
// diff[i]=prices[i]-prices[i-1];
// }
// int res=0;
// for(int i=1;i<len;i++){//差分数组中大于0的就是盈利的值
// if(diff[i]>0) res+=diff[i];
// }
// return res;
// }
//动规
//对比 买卖股票1,只有dp[i][1]的递推公式改变
//dp[i][0]:第i天不持有股票的最大现金
//dp[i][1]:第i天持有股票的最大现金
public int maxProfit(int[] prices) {
int n=prices.length;
int[][] dp=new int[n][2];
dp[0][0]=0;
dp[0][1]=-prices[0];
for(int i=1;i<n;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]);//change
}
return dp[n-1][0];
}
}
题目描述:
给定一个数组,它的第 i
个元素是一支给定的股票在第 i
天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入:prices = [3,3,5,0,0,3,1,4] 输出:6 解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。 随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。
思路分析:
由于多了限制条件,状态数增加。
dp[i][0]:到第i天,1次都不持有
dp[i][1]:持有第1次
dp[i][2]:不持有第1次
dp[i][3]:持有第2次
dp[i][4]:不持有第2次
代码实现:
class Solution {
public int maxProfit(int[] prices) {
int n=prices.length;
int[][] dp=new int[n][5];
dp[0][0]=0;//dp[i][0]:到第i天,1次都不持有
dp[0][1]=-prices[0];//持有第1次
dp[0][2]=0;//不持有第1次
dp[0][3]=-prices[0];//持有第2次
dp[0][4]=0;//不持有第2次
for(int i=1;i<n;i++){
dp[i][0]=dp[i-1][0];
dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i]);
dp[i][2]=Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);
dp[i][3]=Math.max(dp[i-1][3],dp[i-1][2]-prices[i]);
dp[i][4]=Math.max(dp[i-1][4],dp[i-1][3]+prices[i]);
}
return dp[n-1][4];
}
}