[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];
    }
}
相关文章
相关标签/搜索