朴素的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;
}
};