Leetcode Best Time to Buy and Sell Stock IV(最大子段和)

樸素的O(n^2)過不了,這裏借鑑前人的思想,總結一下。

主要利用棧維護對後面產生影響的字段,然後利用貪心的思想逐步合併。

首先,找到每一對最低點(vx),最高點(px);

其次,合併當前(vx, px) 與棧內的點對(top_vx, top_px),分兩種情況

1、若top_vx  >= vx,考慮到vx處在更低點,(top_vx, top_px)對後面的點對不會有影響,則對(top_vx, top_px)計算價值並出棧;

2、若top_px <= px(ps:此時top_vx  < vx), 

      a、若最優解只包含兩對點的其中一對,顯然可以合併兩對點爲(top_vx, px)最優;

      b、若最優解中包含兩對點,則可將兩對點轉化成(top_vx, px), (vx, top_ px), 其中(vx, top_ px)對後面的點對不會有影響,則對(vx, top_ px)對計算價值並出棧,同時更新(vx, px)->(top_vx, px);

最後,將棧內的點對全部計算價值(顯然棧內的點對都不必合併)。

class Solution {
        stack< pair<int, int> > waiting;
        vector<int> profits;
public:
    int maxProfit(int k, vector<int>& pr) {
        int len = pr.size();
        if(len < 2 || k < 1) return 0;
        while(!waiting.empty()) waiting.pop();
        profits.clear();
        
        int posv, posp = -1;
        while(true)
        {
            for(posv = posp + 1; (posv + 1) < len && pr[posv] >= pr[posv + 1]; posv++);
            for(posp = posv + 1; (posp + 1) < len && pr[posp] <= pr[posp + 1]; posp++);
            if(posp >= len) break;
            
            for(; !waiting.empty() && pr[waiting.top().first] >= pr[posv]; waiting.pop())
            {
                profits.push_back(pr[waiting.top().second] - pr[waiting.top().first]);
            }
            for(; !waiting.empty() && pr[waiting.top().second] <= pr[posp]; waiting.pop())
            {
                profits.push_back(pr[waiting.top().second] - pr[posv]);
                posv = waiting.top().first;
            }
            waiting.push(make_pair(posv, posp));
        }
        
        for(; !waiting.empty(); waiting.pop())
        {
            profits.push_back(pr[waiting.top().second] - pr[waiting.top().first]);
        }
        
        int ans = 0;
        if(k >= profits.size()) 
        {
            ans = accumulate(profits.begin(), profits.end(), 0);
        }
        else
        {
            nth_element(profits.begin(), profits.begin() + k - 1, profits.end(), greater<int>());
            ans = accumulate(profits.begin(), profits.begin() + k, 0);
        }
        
        return ans;
    }
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章