一道小面試算法題的思路

一道小算法題的思路

有這麼一道小面試算法題:給定一個長度爲 n 的整數數組,下標爲 i 的元素表示第 i 天某個股票的價格,每次最多持有一股,每次買賣最多一股,在最多隻買賣一次的狀況下(先買後賣,不考慮融券等複雜形式),最大的收益是多少。面試

先考察一下可能的數據:算法

0   1   2   3   4   5   6   7
12   9   6  10   8  22  20  15

因爲是先買後賣,從數據上看,是在 2 處買入,5 處賣出時,獲得收益爲 16 最大。數組

而在股票一直下跌的狀況下,不買不賣,獲得的收益爲 0 最大。優化

  1. o(n^2) 直觀算法code

    最簡單的思路,就是從前向後逐個計算收益,求最大收益,以下:it

    price[n]
     max_profit = 0
     for i = 0...n-2:
         for j = i+1...n-1:
             profit = price[j] - price[i]
             if profit > max_profit:
                 max_profit = profit

    這個算法的複雜度爲 o(n^2) ,能不能繼續優化?基礎

  2. o(n) 算法數據

    用概括法分析一下,在第 n-1 天時,最大收益爲 max_profit ,其中最小的價格爲 min_price,那麼第 n 天時,最大的收益計算爲:co

    if price[n] - min_price > max_profit:
         max_profit = price[n] - min_price

    所以,可把算法改成:

    price[n]
     max_profit = 0
     min_price = price[0]
     for i = 1...n-1:
         profit = price[i] - min_price
         if profit > max_profit:
             max_profit = profit
         if min_price > price[i]:
             min_price = price[i]

    變化爲 o(n) 複雜度。

  3. 推廣變化

    如今,考慮更加複雜的形式,先來個容許不限次數的買賣,那麼,在每個遞增的子區間,都能獲得收益,總收益爲各個收益的和:

    price[n]
     sum_profit = 0
     for i = 1...n-1:
         profite = price[i] - price[i-1]
         if profite > 0:
             sum_profit += profit

    再複雜一點,容許進行融券形式(即容許從券商借出後先賣後買),一樣限制最多持有或融入 1 股,在結束前使得手上股票數爲 0 。這種規則下,股票價格升降都會獲得收益,總收益爲:

    price[n]
     sum_profit = 0
     for i = 1...n-1:
         profite = price[i] - price[i-1]
         if profite < 0:
             sum_profite += -profite
         else:
             sum_profite += profite

    在此基礎上,還能夠放開一些限制條件,如不限制持有的數量等等。更進一步,可設定一個收益目標,符合收益目標的買賣組合,這樣就更加現實意義有意思了。

相關文章
相關標籤/搜索