首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在一天内买卖股票

在一天内买卖股票
EN

Stack Overflow用户
提问于 2012-02-09 22:06:02
回答 3查看 10.4K关注 0票数 1

我在一次面试中被问到这个问题:

Best Time to Buy and Sell Stock

假设你有一个数组,它的第i个元素是给定股票在第一天的价格。如果你只被允许买一股股票,卖出一股股票,设计一个算法来找到买卖的最佳时间。我能够给出一个O(n)算法。

虽然面试官问了我一个接下来的问题,“买一个,卖一个”的情况是什么,然后是“买一个,卖一个”,这意味着一天有两个交易,最大化利润。我能够给出一个O(n^2)算法。但是面试官说这是可以改进的。有O(n)算法吗?

面试官说,你不能同时买两股。你必须买一个卖出,然后在另一个时间买一个,然后再卖。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-02-09 22:32:47

原始问题的reference中给出的O(n)解决方案为原始数组的每个前缀提供了最佳的“买一卖一”的答案。该算法也可以进行简单的修改,以应对“向后”的情况;即“先卖一后买一”,即从数组向后计算;这相当于对数组的每个后缀都有一个“先买一后卖一”的答案。

现在,在“买,卖,买,卖”的情况下,我们有了一些点(在第一次卖出之后),我们在数组中的某个地方,比如b。对于这个断点,最好的解决方案是0..b的最佳前缀解决方案和b+1..n的最佳后缀解决方案。最好的“买,卖,买,卖”总体上就是这些最优解决方案中最优的。

因此,要解决O(n)中的"buy,sell,buy,sell“,您可以求解O(n)中的前缀,O(n)中的后缀,然后为每个断点计算最佳- So nO(1)。这是一个使用O(n)空间的O(n)算法。

票数 1
EN

Stack Overflow用户

发布于 2012-12-25 06:42:05

它可以优化为只有一个for循环,但其思想基本上是相同的:

代码语言:javascript
运行
复制
int maxProfit(vector<int> &prices) {        
    if (prices.empty()) return 0;        

    int n = prices.size();
    int lHolding = prices[0], rHolding = prices[n-1];
    int lMax = 0, rMax = 0;        

    vector<int> profit(n);

    for (int i = 1; i < n; i++) {            
        if (prices[i] > lHolding) {
            lMax = max(lMax, prices[i] - lHolding);
        } else {
            lHolding = prices[i];
        }

        profit[i] += lMax;

        int right = n - 1 - i;

        if (rHolding > prices[right]) {
            rMax = max(rMax, rHolding - prices[right]);
        } else {
            rHolding = prices[right];
        }

        profit[right] += rMax;            
    }

    return *max_element(profit.begin(), profit.end());        
}
票数 0
EN

Stack Overflow用户

发布于 2012-12-25 08:56:07

我来晚了,但它在这里。首先,borrible给出的解决方案不是很清楚,因为有人可以实现它并获得O(n^2)。这只是通过循环遍历b,对于每个b,计算前缀和后缀,每个前缀和后缀都是O(n),所以加在一起就是O (n) *(n),其中(N)来自b=1...n。这意味着结果是O(n^2)。

要实现该描述,使其在O(n)中运行,需要认识到前缀和后缀是独立的,并且可以像Daniel实现的那样单独运行。

这个解决方案的问题是它需要O(n)空间。假设您的股票跟踪是1千兆点(例如,如果您要迭代两年的数据,这是非常常见的),那么您将导致内存使用量激增。

如果我是面试官,下一个逻辑问题是:是否有可能删除内存要求?

让我试一试。其中大部分只是解决基本的数学问题。

我们有一个数组价格为0...n-1。

在最初的问题中,我们想要找到r,s,0<=r

P= pricess - pricesr

是最大化的。

在新问题中,我们想要找到i,j,k,l,其中0<=i

Q= pricesj-pricesi+pricesl-pricesk

是最大化的。

(假设n>=4,即没有退化的情况,我们可以很容易地处理)

假设我们解决了原来的问题,那么新问题的解决方案可以分为3种情况:

  1. i=r
  2. i
  3. i=r

实际上很容易通过还原荒谬来证明这一点(即假设不是,然后将i或k扰动为r,将j或l扰动为s。这种扰动将增加q,这与最初的假设相矛盾)。

好的,解决方案很简单:

a.在O(n)中找到r,s

b.检查O(n)中的情况1

c.检查O(n)中的情况2

d.检查O(n)中的情况3

e.返回b,c,d的最大值。

实际上,b、c和d可以在n次迭代中执行。总和是2O(N)+ O(1),这是O(n)。变量的数量也是固定的,所以空间需求是O(1)。

代码语言:javascript
运行
复制
int maxProfit(vector<int> &prices) {        
    int n = prices.size();

    int b, a;
    int m1 = 0;
    int hb;

    b = a = 0;
    hb = 0;
    for (int i = 1; i < n; i++) {
        if (prices[i] < prices[hb]) {
            hb = i;
        }
        if (prices[i] - prices[hb] > m1) {
            m1 = prices[i] - prices[hb];
            b = hb; a = i;
        }
    }

    int before = 0, after = 0;
    if (b > 0) {
        int bb, ba;
        before = 0;
        int bhb;

        bb = ba = 0;
        bhb = 0;
        for (int i = 0; i < b-1; i++) {
            if (prices[i] < prices[bhb]) {
                bhb = i;
            } 
            if (prices[i] - prices[bhb] > before) {
                before = prices[i] - prices[bhb];
                bb = bhb; ba = i;
            }
        }
    }
    if (a < n) {
        int ab, aa;
        int ahb;

        ab = aa = a+1;
        ahb = a+1;
        after = 0;
        for (int i = a+2; i < n; i++) {
            if (prices[i] < prices[ahb]) {
                ahb = i;
            } 
            if (prices[i] - prices[ahb] > after) {
                after = prices[i] - prices[ahb];
                ab = ahb; aa = i;
            }
        }

    }


    int hmb = before + m1;
    int hma = after + m1;
    int hm = max(hmb,hma);

    int tm = b;
    for (int j = b+1; j < a; j++) {
        if (prices[j] > prices[tm]) {
            tm = j;
        }
        m1 = prices[tm] - prices[b] + prices[a] - prices[j];
        hm = max(hm,m1);
    }

    return hm;
}

可能有一些退化的情况我忘记了,但我花了更长的时间来写这个回复,而不是想出简单的解决方案,所以如果有bug,你就得靠自己了。不过,数学计算似乎是可行的,所以它可能是正确的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9212299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档