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 1

Note

只有一次交易,那么将prices[]数组循环一次,每次循环更新prices[]历史最小值,并与当日价格相减得到当日利润,同步更新profit最大值。

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.

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 2

Note

可以有无限次交易,那么在所有股票上涨的区间都进行交易。

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.

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];
    }
}

linspiration
161 声望53 粉丝

引用和评论

0 条评论