Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Example 1:
Input: [7, 1, 5, 3, 6, 4]
Output: 5
max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)
Example 2:
Input: [7, 6, 4, 3, 1]
Output: 0
In this case, no transaction is done, i.e. max profit = 0.
1.解题思路
想到用动态规划,首先寻找状态,dp[i] 表示第i天能获得的最大收益,然后考虑状态转移,因为最多只允许1次股票交易,所以我们可以维护一个minPrice,对于dp[i],如果prices[i]比minPrice还要小,那么第i天肯定不应该卖出股票;如果prices[i]比minPrice大,我们就需要比较prices[i]-minPrice的收益和dp[i-1]的收益,以确定第i天要不要卖股票。
2.代码
public class Solution {
public int maxProfit(int[] prices) {
if(prices.length<2) return 0;
int[] dp=new int[prices.length];
int minPrice=prices[0];
dp[0]=0;
for(int i=1;i<prices.length;i++){
if(prices[i]>=minPrice){
dp[i]=Math.max(dp[i-1],prices[i]-minPrice);
}
else{
minPrice=prices[i];
dp[i]=dp[i-1];
}
}
return dp[prices.length-1];
}
}
Best Time to Buy and Sell Stock II
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
1.解体思路
该题可以进行无数次股票交易,所以我们选择贪心算法,即只要发现第i天价格比前一天高,就进行交易。递增区间(1,4,5)就相当于昨天低价1块买入,今天4块卖出,收益3块,再4块买入,明天再5块卖出,共收益3+1块。
2.代码
public class Solution {
public int maxProfit(int[] prices) {
if(prices.length<2) return 0;
int maxProfit=0;
for (int i = 1; i < prices.length; i++) {
maxProfit += prices[i] > prices[i-1] ? prices[i] - prices[i-1] : 0;
}
return maxProfit;
}
}
Best Time to Buy and Sell Stock III
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.
1.解体思路
本题还是动态规划,题目说最多进行2次交易,我们很容易就想到用left[i]和right[i]两个数组来记录状态,
left[i]表示从0到i天获得的最大收益,right[i]表示从i到最后一天获得的最大收益,最后遍历所有的left[i]和right[i],使得left[i]+right[i]的和最大,即为题目的解。
分别分析left[i]和right[i].
1)left[i], 表示从0到i天获得的最大收益, 其实和第一题一样,借助minPrice;
2)right[i],表示从第i天买入开始的最大收益,相反,我们需要借助maxPrice,假设prices[i]比maxPrice小,那么通过比较right[i+1]和maxPrice-prices[i]来确定第i天是否要买入股票;如果prices[i]比maxPrice大,那么right[i]=right[i+1]维持不变,并更新maxPrice的值,以便进行下次比较。
2.代码
public class Solution {
public int maxProfit(int[] prices) {
//at most two transactions means we can seperate the problem to left array & right array
if(prices.length<2) return 0;
int[] left=new int[prices.length];
int[] right=new int[prices.length];
//left side is the same as "Best Time to Buy and Sell Stock"
int minPrice=prices[0];
for(int i=1;i<prices.length;i++){
if(prices[i]>=minPrice){
left[i]=Math.max(left[i-1],prices[i]-minPrice);
}
else{
left[i]=left[i-1];
minPrice=prices[i];
}
}
//right side starts from the end of array.
int maxPrice=prices[prices.length-1];
for(int i=prices.length-2;i>=0;i--){
if(prices[i]<maxPrice){
right[i]=Math.max(maxPrice-prices[i],right[i+1]);
}
else{
right[i]=right[i+1];
maxPrice=prices[i];
}
}
//get the max of left[i]+right[i];
int max=0;
for(int i=0;i<prices.length;i++){
max=Math.max(max,left[i]+right[i]);
}
return max;
}
}
Best Time to Buy and Sell Stock IV
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most k transactions.
1.解体思路
看到这题,我们就明白了其实前两题II和III都是这一题的个例,II是允许有无数次的交易,即k>n/2,的情况,我们可以用贪心算法;而III其实就是k=2的情况。
我们需要维护两个数组,globali表示到第i天发生j次交易所获得的最大收益,locali表示到第i天发生j次交易,并且第j次交易发生在这一天所获得的最大收益。
globali=Math.max(globali-1,locali);
globali-1表示第i天不发生交易,j次交易都在i天之前就已完成;
locali表示第j次交易发生在第i天。
locali=Math.max(globali-1+Math.max(0,prices[i]-prices[i-1]),locali-1+prices[i]-prices[i-1])
globali-1+Math.max(0,prices[i]-prices[i-1])表示在前i-1天的全局收益基础上加上第i天可以得到的收益,如果prices[i]-prices[i-1]为负,则说明会亏损,所以我们就当作再i天又再次买入,所以收益不变;
locali-1+prices[i]-prices[i-1]:locali-1表示在第i-1天有进行第j次交易,现在我们把这次交易移到第i天。
2.代码
public class Solution {
public int maxProfit(int k, int[] prices) {
if(prices.length<2) return 0;
if(k+k>prices.length){
int sum=0;
for(int i=1;i<prices.length;i++){
if(prices[i]>prices[i-1]){
sum+=prices[i]-prices[i-1];
}
}
return sum;
}
int[][] local_dp=new int[prices.length][k+1];
int[][] global_dp=new int[prices.length][k+1];
for(int i=1;i<prices.length;i++){
for(int j=1;j<=k;j++){
int diff=prices[i]-prices[i-1];
local_dp[i][j]=Math.max(global_dp[i-1][j-1]+Math.max(diff,0),local_dp[i-1][j]+diff);
global_dp[i][j]=Math.max(global_dp[i-1][j],local_dp[i][j]);
}
}
return global_dp[prices.length-1][k];
}
}
Best Time to Buy and Sell Stock with Cooldown
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)
Example:
prices = [1, 2, 3, 0, 2]
maxProfit = 3
transactions = [buy, sell, cooldown, buy, sell]
1.解体思路
依然是动态规划,寻找状态,因为本题涉及到cooldown,所以第i天的状态我们分为持股和未持股,即维护两个数组,dp_hasstock[i]和dp_nostock[i]分别表示第i天持股和未持股所获得的最大收益。
dp_nostock[i]=Math.max(dp_nostock[i-1],dp_hasstock[i-1]+prices[i]);
未持股分为两种情况,一种是今天cooldown,所以就等于第i-1天卖出了股票后的最大收益;还有一种是今天卖股票,即前一天持股的最大收益加上今天卖出的股票价格:dp_hasstock[i-1]+prices[i]。
dp_hasstock[i]=Math.max(dp_nostock[i-2]-prices[i],dp_hasstock[i-1]);
持股也分为两种情况,一种是昨天cooldown,今天买入股票,所以就等于前天卖出股票后的最大收益减去今天买入股票的价格;另一种情况继续保持之前买入的股票,不进行交易。
2.代码
public class Solution {
public int maxProfit(int[] prices) {
if(prices.length<2) return 0;
int[] dp_hasstock=new int[prices.length];
int[] dp_nostock=new int[prices.length];
dp_hasstock[0]=-prices[0];
dp_nostock[0]=0;
for(int i=1;i<prices.length;i++){
dp_nostock[i]=Math.max(dp_nostock[i-1],dp_hasstock[i-1]+prices[i]);
if(i<2)
dp_hasstock[i]=Math.max(-prices[i],dp_hasstock[i-1]);
else
dp_hasstock[i]=Math.max(dp_nostock[i-2]-prices[i],dp_hasstock[i-1]);
}
return dp_nostock[prices.length-1];
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。