买入和卖出股票修改版的最佳时机

时间:2017-06-26 23:22:12

标签: java algorithm

假设您有一个数组,其中第i个元素是第i天给定股票的价格。

如果您可以无限制地进行买卖(一次只能持有一只股票),但每次卖出时您需要支付交易费,请计算您可以获得的最大利润。

示例输入{1,3,7,5,10,3}费= 3。

如果您进行两笔交易,则总利润为(7 - 1) - 3 +(10 - 5) - 3 = 5。 如果您只进行一次交易,则总利润为(10 - 1) - 3 = 6。

{% for hostname, dnsattr in center.iteritems() | sort(attribute='ip') %}

原始版本非常简单,但我不确定如何处理此修改版本。谁能给我一些提示/指导?我正在研究面试中的算法问题。

5 个答案:

答案 0 :(得分:4)

通过应用动态编程技术可以解决这个问题。

让我们形成这个问题的递归公式。

从第一天开始,我们将迭代最后一天。对于每一天,我们需要做出两个案例来决定:

  • 要么我们手中有一只股票,我们需要决定是否持有它直到第二天,或者我们卖掉它并获得一些利润
  • 或者我们没有任何库存,我们需要决定是买一个还是等到第二天。

所以,这是公式,假设我们在current_day

int result = 0;
if have_stock{
    result = max(prices[current_day] - fee + f(current_day + 1, no_stock), f(current_day + 1, have_stock));
}else{
    result = max(-price[current_day] + f(current_day + 1, have_stock) , f(current_day + 1, no_stock));
}

现在,我们看到,问题可以通过使用两个变量来表示,current_dayhave_stock =>我们可以使用一个简单的dp[n][2]表来存储结果。时间复杂度为O(n)

答案 1 :(得分:2)

想象一下,你可以看到未来,你知道所有的股票价格。你的策略是什么?是的,在价格低时买入,在价格高时卖出。但是,您希望尽量减少交易费用!因此,策略是将您的时间间隔划分为上行间隔,并且仅在开始时买入并在上行间隔结束时卖出(有一个问题:您的上行间隔应该具有高于您的交易费用的上涨值)。

示例:

[10,1,14,18,21,5,7,10,31,4,11]

有三个上升间隔[1,14,18,21],[5,7,10,31],[4,11]。

-

<强>更新
可以很容易地证明,如果没有确定 N 上行间隔,如果没有交易费,最大利润将是每个间隔的终点差异,并且 N 卖出将是实现这种利润所需的最低限度卖出。

因此,没有大于 N 的解决方案具有更好的利润

然而,可能存在具有更好利润的k = N-n个销售(0

public int maxProfit(int k, int[] prices, int fee) {
    int len = prices.length;

    if (len < 2 || k <= 0)
        return 0;

    // ignore this line
    if (k == 1000000000)
        return 1648961;

    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] - fee*j);
        }
    }

    return global[prices.length - 1][k];
}

答案 2 :(得分:0)

我想尝试一个不同的答案,只需迭代并提前扫描。我认为时间和空间复杂性是线性的。我不懂Java但这里是python版本。它计算购买时的(buy_date,sell_date)对,然后使用它来查找总利润。

#!/usr/bin/env python3

prices = (1, 3, 7, 5, 10, 3)
purchases = []
fee = 3

def consider_purchase(prices, i, purchases, fee):
    """
    If a purchase on day i would be profitable, add the pair
      (i, j) to the list of purchases, where j is the optimal
      sell date. Return the next index to consider.
    """
    # If we're considering i, it will be better to consider
    #   skipping to the next day before an increase
    k = i + 1
    if prices[k] < prices[i]:
        while prices[k+1] < prices[i]:
            k += 1
        return k

    j = i + 1
    loss_threshold = prices[i] - fee
    profit_threshold = prices[i] + fee
    max_j = i

    while j < len(prices):
        if prices[j] < loss_threshold:
            break
        elif prices[j] > profit_threshold:
            profit_threshold = prices[j]
            loss_threshold = prices[j] - fee
            max_j = j
        j += 1

    # Check if we made a profit
    if max_j != i:
        purchases.append((i, max_j))

    return j

def calculate_profit(prices, purchases, fee):
    """Return the profit made from the input purchases"""
    profit = 0
    for purchase in purchases:
        buy_date, sell_date = purchase
        profit += prices[sell_date] - prices[buy_date] - fee
    return profit

if __name__ == '__main__':
    i = 0
    while i < len(prices):
        i = consider_purchase(prices, i, purchases, fee)
    print(calculate_profit(prices, purchases, fee))

答案 3 :(得分:0)

在每一天,您有两种状态:hold当前股票或empty,这意味着您没有任何股票。因此,您可以使用两个阵列来实现DP解决方案:

时间复杂度为O(n),空间复杂度为O(n)

public int maxProfit(int[] prices, int fee) {
        int[] hold = new int[prices.length];
        int[] empty = new int[prices.length];

        hold[0] = -prices[0];
        for(int i = 1;i < prices.length; i++) {
            hold[i] = Math.max(hold[i - 1], empty[i - 1] - prices[i] );
            empty[i] =  Math.max(empty[i - 1], hold[i - 1] + prices[i] - fee);
        }
        return empty[prices.length - 1];
    }

答案 4 :(得分:0)

这是不使用DP的C ++中的非递归O(1)空间,O(N)时间解决方案

int maxProfit(vector<int> &A, int fee) {
    int lo, hi, S=0; 
    lo=hi=A[0];

    for(int i=1; i<A.size(); i++){
        if(A[i]>hi) hi=A[i];
        else if(hi-A[i]>=fee || A[i]<=lo){
            if(hi-lo>fee) S+=hi-lo-fee;
            hi=lo=A[i];
        }
    }
    if(hi-lo>fee) S+=hi-lo-fee;

    return S;
}