121 122 123 188 Best Time to Buy and Sell Stock

来源:互联网 发布:出国留学值得吗 知乎 编辑:程序博客网 时间:2024/06/08 04:20

都可以用DP的方法解决



121 

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: 5max. 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: 0In this case, no transaction is done, i.e. max profit = 0.

public class Solution {    public int maxProfit(int[] prices) {        int minPrice  = Integer.MAX_VALUE;        int maxProfit = 0;                for(int i=0; i<prices.length; i++) {            if(prices[i] < minPrice)                minPrice = prices[i];            else                if(prices[i] - minPrice > maxProfit)                    maxProfit = prices[i] - minPrice;        }        return maxProfit;    }}



122

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).


这题更简单,因为不限次数,所以主要是增长的就买

public class Solution {    public int maxProfit(int[] prices) {                int rst = 0;                for(int i=0; i<prices.length-1; i++) {            if(prices[i] < prices[i+1])                rst += prices[i+1] - prices[i];        }                    return rst;    }}



123

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.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).






DP方法的典型套路:因为有两个自由度:交易次数,可交易天数。所以用2维的DP,最开始用的是下面的代码

public class CopyOfSolution {    public int maxProfit(int[] prices) {    int len = prices.length;        // dp[i][j]表示最多有i次机会,有j天可以交易的情况下最多可以获得的利润        int[][] dp = new int[3][len];        int max = 0;                for(int i=1; i<3; i++) {        for(int j=1; j<len; j++) {        int tempMax = -1;                // 获得在第j交易可以获得的最大利润        for(int k=0; k<j; k++)        tempMax = Math.max(tempMax, dp[i-1][k] + prices[j] - prices[k]);                // 第j天可以不交易,也可以交易        dp[i][j] = Math.max(dp[i][j-1], tempMax);                //         max = Math.max(max, dp[i][j]);        }        }                // 可以不用max,直接return dp[2][len-1],因为题目的意思是可以在一天内买进卖出好多次    return max;    }}


超时了,因为有重复计算
tempMax = Math.max(tempMax, dp[i-1][k] + prices[j] - prices[k]);
优化了一下AC:

public class Copy_2_of_Solution {    public int maxProfit(int[] prices) {    if(prices.length < 2)return 0;    int len = prices.length;        int[][] dp = new int[3][len];        int max = 0;                for(int i=1; i<3; i++) {                // 有重复的计算量        // 新增一个变量tempMax,保存dp[i-1][j]后并在第j天买入股票的最大利润        int tempMax = dp[i-1][0] - prices[0];                for(int j=1; j<len; j++) {                // 买入,加prices[j]        dp[i][j] = Math.max(dp[i][j-1], prices[j] + tempMax);        max = Math.max(max, dp[i][j]);                tempMax = Math.max(tempMax, dp[i-1][j] - prices[j]);        }        }            return max;    }}


另外在Discuss发现一个比较直观的解法,两个的trick是(1)整合之前的股票,(2)先考虑最大序号股票的卖出,买入,接着考虑第序号的卖出,买入





public class Solution {    public int maxProfit(int[] prices) {    if(prices.length < 2)return 0;    int len = prices.length;            // maxProfit[i]表示卖出第i个股票可获得的利润    int[] maxProfit = new int[3];        // lowestBuyPrice[i]相当于以多少钱买进第i个股票    // 负数就表示买进第i个股票还有多少利润    int[] lowestBuyPrice = new int[3];        // 初始化    for(int i=1; i<3; i++)lowestBuyPrice[i] = Integer.MAX_VALUE;        for(int i=0; i<len; i++) {    for(int j=2; j>=1; j--) {        // 注意DP的顺序,因为如果先求lowestBuyPrice[j]会影响maxProfit[j]    maxProfit[j] = Math.max(maxProfit[j], prices[i] - lowestBuyPrice[j]);        // prices[i] - maxProfit[j-1]表示相当于以多少的净价格买进股票i(整合了之前的股票)    lowestBuyPrice[j] = Math.min(lowestBuyPrice[j], prices[i] - maxProfit[j-1]);    }    }            return maxProfit[2];    }}







188


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.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).


与前面那个就类似了,唯一的trick就是当k很大的时候要采用第二种解法




My code:

public class Solution {    public int maxProfit(int k, int[] prices) {        if(prices.length < 2)return 0;        int len = prices.length;                // if k 比较大,那么就可以只要有上升就可以购买        if(k >= len / 2)return quickSolve(prices);                int[] maxProfit = new int[1+k];        int[] lowestBuyPrice = new int[1+k];                // maxProfit 初始化就是为0的,所以不需要额外的初始化,后面求的是Math.max        // lowestBuyPrice表示等效于多少钱买进,因为求的是Math.min,需要初始化        for(int i=0; i<=k; i++)lowestBuyPrice[i] = Integer.MAX_VALUE;                for(int i=0; i<len; i++) {        // 第0天不需要考虑        for(int j=k; j>=1; j--) {                // 既然求maxProfit,这天肯定不买进了        maxProfit[j] = Math.max(maxProfit[j], prices[i] - lowestBuyPrice[j]);                lowestBuyPrice[j] = Math.min(lowestBuyPrice[j], prices[i] - maxProfit[j-1]);        }        }                return maxProfit[k];    }private int quickSolve(int[] prices) {int rst = 0;for(int i=0; i<prices.length-1; i++)if(prices[i+1] - prices[i] > 0)rst += prices[i+1] - prices[i];return rst;}}












123

1 0
原创粉丝点击