[LintCode/LeetCode] Best Time to Buy and Sell Stock I II III IV

Problem

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

Given an example [3,2,3,1,2], return 1code

Note

只有一次交易,那麼將prices[]數組循環一次,每次循環更新prices[]歷史最小值,並與當日價格相減獲得當日利潤,同步更新profit最大值。ip

Solution

public class Solution {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length == 0) return 0;
        int profit = 0;
        int min = prices[0];
        for (int i = 1; i < prices.length; i++) {
            min = Math.min(min, prices[i]);
            profit = Math.max(prices[i] - min, profit);
        }
        return profit;
    }
}

Problem

Say you have an array for which the ith element is the price of a given stock on day i.element

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

Example

Given an example [2,1,2,0,1], return 2it

Note

能夠有無限次交易,那麼在全部股票上漲的區間都進行交易。io

Solution

class Solution {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length == 0) return 0;
        int profit = 0;
        for (int i = 1; i < prices.length; i++) {
            profit += prices[i] > prices[i-1] ? prices[i] - prices[i-1] : 0;
        }
        return profit;
    }
}

Problem

Say you have an array for which the ith element is the price of a given stock on day i.class

Design an algorithm to find the maximum profit. You may complete at most two transactions.循環

Example

Given an example [4,4,6,1,1,4,2,5], return 6.

Note

買賣股票III有幾個值得注意的地方,首先left[0], right[len-1]在循環以前會自動賦0。其二,是分配left[]right[]的空間都要比prices.length大1。
這道題使用雙向動態規劃的作法,從prices[0]向右找prices[i]以左的最大收益left[i],從prices[len-1]向左找prices[i]以右的最大收益right[i]
最後遍歷全部left[i] + right[i],獲得收益最大值。

Solution

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (prices == null || len == 0) return 0;
        int[] left = new int[len+1];
        int[] right = new int[len+1];
        int min = prices[0];
        int max = prices[len-1];
        int profit = 0;
        for (int i = 1; i < len; i++) {
            min = Math.min(prices[i], min);
            left[i] = Math.max(prices[i] - min, left[i-1]);
        }
        for (int i = len - 2; i >= 0; i--) {
            max = Math.max(prices[i], max);
            right[i] = Math.max(right[i+1], max - prices[i]);
        }
        for (int i = 0; i < len; i++) {
            profit = Math.max(profit, left[i] + right[i]);
        }
        return profit;
    }
}

Problem

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.

Example

Given prices = [4,4,6,1,1,4,2,5], and k = 2, return 6.

Note

首先分析k與len的關係,若是k > len / 2,至關於比每兩天交易一次(昨天買今天賣,明天買後天賣)還要多,那麼就存在在同一天買入並賣出的狀況。那麼就至關於股票交易II中的作法,在全部上漲的狀況下都作了交易,返回sum

而後分析非上述狀況的k值:創建兩個數組,數組local[i][j]表示在第i正好作完j次交易的收益,數組global[i][j]表示在第i已經作完j次交易的收益。

global[i][j]二次優化收益,以前作過的交易總數可能等於j,也可能大於j

local[i][j]當次優化收益,分爲兩種狀況
i-1天作j-1次交易的二次優化收益global[i-1][j-1],加上一次優化交易的利潤:取第i-1天買入、第i天賣出的利潤和0的較大者(0表示今日買入並賣出的狀況),以達成第j次交易;
i-1天作j次交易的當次優化收益local[i-1][j],加上一次等效交易的利潤:即第i-1天完成j次交易等效於第i天完成j次交易的狀況:假設第i天股票價格繼續上漲,就至關於第i-1賣出後繼續買入,第i天又賣出,至關於第i-1天沒有交易操做,第i天賣出才完成了第j次交易。
local[i][j]最後取上述兩種狀況的較大值。

Solution

1.

class Solution {
    public int maxProfit(int k, int[] prices) {
        int len = prices.length;
        if (prices == null || len == 0) return 0;
        if (k + k > len) {
            int sum = 0;
            for (int i = 1; i < len; i++) {
                sum += prices[i] > prices[i-1] ? prices[i] - prices[i-1] : 0;
            }
            return sum;
        }
        int[][] local = new int[len][k+1];
        int[][] global = new int[len][k+1];
        for (int i = 1; i < len; i++) {
            int diff = prices[i] - prices[i-1];
            for (int j = 1; j <= k; j++) {
                local[i][j] = Math.max(global[i-1][j-1] + Math.max(diff, 0), 
                                        local[i-1][j] + diff);
                global[i][j] = Math.max(global[i-1][j], local[i][j]);
            }
        }
        return global[len-1][k];
    }
}

2.

public class Solution {
    public int maxProfit(int k, int[] prices) {
        int n = prices.length;
        if (n < 2) return 0;
        if (k + k > n) {
            int profit = 0;
            for (int i = 1; i < n; i++) 
                if (prices[i] > prices[i-1]) 
                    profit += prices[i] - prices[i-1];
            return profit;
        }
        int[][] dp = new int[k+1][n];
        for (int i = 1; i <= k; i++) {
            int max = -prices[0];
            for (int j = 1; j < n; j++) {
                dp[i][j] = Math.max(dp[i][j-1], prices[j]+max);
                max = Math.max(max, dp[i-1][j]-prices[j]);
            }
        }
        return dp[k][n-1];
    }
}
相關文章
相關標籤/搜索