①、买卖股票的最佳时机
给定一个数组
prices
,它的第i
个元素prices[i]
表示一支给定股票第i
天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回
0
。
事例:
输入:[7,1,5,3,6,4] 输出:5 解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
思路:
①、贪心算法:遍历股票价值,边记录当前范围内的最小值(购入时刻),然后计算当天利润(卖出时刻),求得最大值即可。
代码:
public int maxProfit(int[] prices) {
if(prices.length == 1) return 0;
int minPrice = prices[0];
int res = 0;
for(int i = 1;i < prices.length;i++){
minPrice = Math.min(minPrice,prices[i]);
int profit = prices[i] - minPrice;
res = Math.max(res,profit);
}
return res;
}
②、动态规划:当天股票只有两种状态,持有/不持有。维持持有状态:当天购入,则有前一天不持有状态减去当天价值,或者直接维持前一天的持有状态,即不卖股票。维持不持有状态:当前卖出,则由前一天的持有状态加上当天价值,或者维持前一天的不持有状态。由于这道题是只卖出一次,故持有和不持有股票的状态只能互相转变一次,即第一次持有股票只能为0 - 当天价值。
动态规划:
dp定义及含义:dp为一个二维数组,dp[i][0]表示第i天持有股票的最大金额,dp[i][1]表示第i天不持有股票的最大金额
状态转移方程:dp[i][0] = Math.max(dp[i - 1][0],-price[i]) dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] + price[i])
初始化:dp[0][0] = -price[0] dp[0][1] = 0
遍历顺序:正序遍历股票赋值即可
dp[price.length - 1][1]即为最大利润
代码:
public int maxProfit(int[] prices) {
// if(prices.length == 1) return 0;
// int minPrice = prices[0];
// int res = 0;
// for(int i = 1;i < prices.length;i++){
// minPrice = Math.min(minPrice,prices[i]);
// int profit = prices[i] - minPrice;
// res = Math.max(res,profit);
// }
// return res;
//动态规划
if(prices.length == 1) return 0;
int[][] dp = new int[prices.length][2];
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]);
dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] + prices[i]);
}
return dp[prices.length - 1][1];
}
②、买卖股票的最佳时机Ⅱ
给你一个整数数组
prices
,其中prices[i]
表示某支股票第i
天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
事例:
输入: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定义及含义:dp为一个二维数组,dp[i][0]表示第i天持有股票的最大金额,dp[i][1]表示第i天不持有股票的最大金额
状态转移方程:dp[i][0] = Math.max(dp[i - 1][0],dp[i - 1][1] - price[i]) dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] + price[i])
初始化:dp[0][0] = -price[0] dp[0][1] = 0
遍历顺序:正序遍历股票赋值即可
dp[price.length - 1][1]即为最大利润
代码:
public int maxProfit(int[] prices) {
//贪心算法 从第二天开始记录每两天的利润 累加正利润
// int res = 0;
// for(int i = 1;i < prices.length;i++){
// res += Math.max(prices[i] - prices[i - 1],0);
// }
// return res;
//动态规划 dp[i][0] 表示第i天持有股票的金额 dp[i][1] 表示第i天不持有股票的金额
int[][] dp = new int[prices.length][2];
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],dp[i - 1][1] - prices[i]);
dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] + prices[i]);
}
return dp[prices.length - 1][1];
}