Maximizing profit for given stock quotes

后端 未结 9 1899
無奈伤痛
無奈伤痛 2020-12-07 09:45

I was asked this question while interviewing for a startup and saw this again in the recent contest at

Code Sprint:systems

**The question :

You are

相关标签:
9条回答
  • 2020-12-07 10:21

    I agree with the logic of your method but there is no need to do recursive processing or global maxima searches. To find the sell/buy days you just need to look at each day once:

    The trick is to start from the end. Stock trade is easy if your travel backwards in time!

    If you think code is easier to read than words, just skip my explanation, but here goes:

    Reading from the end, look at price of that day. Is this the highest price so far (from the end), then sell! The last day (where we start reading) you will always sell.

    Then go to the next day (remember, backwards in time). Is it the highest price so far (from all we looked at yet)? - Then sell all, you will not find a better day. Else the prices increase, so buy. continue the same way until the beginning.

    The whole problem is solved with one single reverse loop: calculating both the decisions and the profit of the trade.

    Here's the code in C-like python: (I avoided most pythonic stuff. Should be readable for a C person)

    def calcprofit(stockvalues): 
        dobuy=[1]*len(stockvalues) # 1 for buy, 0 for sell
        prof=0
        m=0
        for i in reversed(range(len(stockvalues))):
            ai=stockvalues[i] # shorthand name
            if m<=ai:
                dobuy[i]=0
                m=ai
            prof+=m-ai
        return (prof,dobuy)  
    

    Examples:

    calcprofit([1,3,1,2]) gives (3, [1, 0, 1, 0])
    calcprofit([1,2,100]) gives (197, [1, 1, 0])
    calcprofit([5,3,2])   gives (0, [0, 0, 0])
    calcprofit([31,312,3,35,33,3,44,123,126,2,4,1]) gives
     (798, [1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0])
    

    Note that m is the highest stock price we have seen (from the end). If ai==m then the profit from stocks bought at the the step is 0: we had decreasing or stable price after that point and did not buy.

    You can verify that the profit calculation is correct with a simple loop (for simplicity imagine it's within the above function)

    stock=0
    money=0
    for i in range(len(stockvalues)):  
        if dobuy[i]:
            stock+=1
            money-=stockvalues[i]
        else:
            money+=stockvalues[i]*stock
            stock=0
    print("profit was: ",money)
    
    0 讨论(0)
  • 2020-12-07 10:23

    0.Start from end of array so that no need to recurse
    1. smax = maximum stock price from the list
    2.Then find the profit by assuming you have bought all the stocks till smax and you sell it at the price of smax

              public static void main(String[] args) {
    
              Scanner sc = new Scanner(System.in);
              int numOfTestCase = sc.nextInt();
              for (int i = 0; i < numOfTestCase; i++) {
                     int n = sc.nextInt();
                     long profit = 0;
                     int[] stockPrice = new int[n];
    
                     for (int j = 0; j < n; j++) {
                           stockPrice[j] = sc.nextInt();
                     }
    
                     int currMax = Integer.MIN_VALUE;
    
                     for (int j = n - 1; j >= 0; j--) {
                           if (currMax < stockPrice[j]) {
                                  currMax = stockPrice[j];
                           }
                           profit += (currMax - stockPrice[j]);
                     }
                     System.out.println(profit);
    
    
              }
       }
    
    0 讨论(0)
  • 2020-12-07 10:26

    Another O(n) solution for this task can be done by using local minimum and maximum finding the best deference (profit) between max and min knowing that max should have greater index then min. We also need to look at previous best local min (C# implementation).

    public int[] GetBestShareBuyingStrategy(int[] price)
        {
            var n = price.Length;
            if (n <= 1)
                return null;
    
            var profit = 0;
            var min = 0;
            var max = 0;
            var lmin = 0;
    
            for (var i = 1; i < n; i++)
            {
                var lmax = i;
                var lp = price[lmax] - price[lmin];
                if (lp <= 0)
                {
                    lmin = i;
                }
                else
                {
                    var tp = price[lmax] - price[min];
                    if (lp > tp && lp > profit)
                    {
                        min = lmin;
                        max = lmax;
                        profit = lp;
                    }
                    else if (tp > profit)
                    {
                        max = lmax;
                        profit = tp;
                    }
                }
            }
    
            return profit > 0
                ? new [] {min, max}
                : null;
        }
    
    
    
        [Test]
        [TestCase(new[] { 10, 9, 8, 7, 3 })]
        [TestCase(new[] { 5, 5, 5, 5, 5 })]
        [TestCase(new[] { 5, 4, 4, 4 })]
        [TestCase(new[] { 5, 5, 3, 3 })]
        public void GetBestShareBuyingStrategy_When_no_sense_to_buy(int[] sharePrices)
        {
            var resultStrategy = GetBestShareBuyingStrategy(sharePrices);
            Assert.IsNull(resultStrategy);
        }
    
        [Test]
        [TestCase(new[] { 10, 8, 12, 20, 10 }, 1, 3)]
        [TestCase(new[] { 5, 8, 12, 20, 30 }, 0, 4)]
        [TestCase(new[] { 10, 8, 2, 20, 10 }, 2, 3)]
        [TestCase(new[] { 10, 8, 2, 20, 10 }, 2, 3)]
        [TestCase(new[] { 10, 2, 8, 1, 15, 20, 10, 22 }, 3, 7)]
        [TestCase(new[] { 1, 5, 2, 7, 3, 9, 8, 7 }, 0, 5)]
        [TestCase(new[] { 3, 5, 2, 7, 3, 9, 8, 7 }, 2, 5)]
        public void GetBestShareBuyingStrategy_PositiveStrategy(int[] sharePrices, int buyOn, int sellOn)
        {
            var resultStrategy = GetBestShareBuyingStrategy(sharePrices);
            Assert.AreEqual(buyOn, resultStrategy[0]);
            Assert.AreEqual(sellOn, resultStrategy[1]);
        }
    
    0 讨论(0)
  • 2020-12-07 10:33

    here is more simple and easy to understand algo;

        private static void BuyOnceAndSellONce()
        {
            int[] stock = new int[] { 100, 180, 260, 310, 40, 535, 695 };
            int profit = 0;
            int minimumPrice = int.MaxValue;
            for (int i = 0; i < stock.Length; i++)
            {
                profit = Math.Max(profit, stock[i] - minimumPrice);
                minimumPrice = Math.Min(stock[i], minimumPrice);
    
            }
            Console.WriteLine("profit "  + profit);
        }
    
        private static void MultipleBuySellButNonOverlappingTransactions()
        {
            int[] stock = new int[] { 100, 180, 260, 310, 40, 535, 695 };
            int totalProfit = 0;
            int currentProfit = 0;
            for (int i = 1; i < stock.Length;i++)
            {
                currentProfit = stock[i] - stock[i - 1];
                if (currentProfit > 0)
                    totalProfit += currentProfit;
            }
    
            Console.WriteLine(totalProfit);
        }
    
    0 讨论(0)
  • 2020-12-07 10:34
    private static int MaxProfit(int[] A)
            {
                if (A.Length == 0)
                    return 0;
                Stack<int> repositoryStack = new Stack<int>();
                int maxProfit = 0;
                int tempProfit;
                for (int i = 0; i < A.Length; i++)
                {
                    if (repositoryStack.Count == 0)
                    {
                        repositoryStack.Push(i);
                        continue;
                    }
                    while (repositoryStack.Count != 0 && A[i] < A[repositoryStack.Peek()])
                    {
                        repositoryStack.Pop();
                    }
                    if (repositoryStack.Count != 0 && A[i] > A[repositoryStack.Peek()])
                    {
                        tempProfit = A[i] - A[repositoryStack.Peek()];
                        if (tempProfit > maxProfit)
                            maxProfit = tempProfit;
                    }
                    if(repositoryStack.Count == 0)
                        repositoryStack.Push(i);
                }
                return maxProfit;
            }
    
    0 讨论(0)
  • 2020-12-07 10:37

    Another way to look at it:
    In pre-processing, for each element a[i] find a[j] s.t. j > i and it maximizes (a[j] - a[i])
    so, the Best you can do for a price at a[i] is Buy at a[i] and Sell at a[j]. If there exists no a[j] s.t. a[j] > a[i] then a[i] is not a Buy point at all.

    Preprocessing time: O(N)

    S[N-1] = A[N-1];
    for(int i=N-2; i>=0; --i)
           S[i] = max(A[i], S[i+1]);
    

    Here, S[i] is the price at which you should sell a[i].

    Summing up total Profit: O(N)

    long long int Profit = 0;
        for(int i=0;i<N;++i)
              Profit += max(0,  (S[i]-A[i]) );
    
    0 讨论(0)
提交回复
热议问题