Leetcode Best Time to Buy and Sell Stock IV

来源:互联网 发布:linux cp复制文件夹 编辑:程序博客网 时间:2024/05/29 14:11

Leetcode Best Time to Buy and Sell Stock IV,本题主要是找出最大值与买卖次数的关系,很快可以求得结果。

卖买次数与k的关系分析

  1. 首先我们知道当次数不限时,只需要在所有上升部分的起点买入,然后在上升部分的终点卖出即可。
  2. 当次数大于上升段数(设为max)时,与1相同。
  3. k < max时,我们需要在这些部分中进行取舍。首先,我们可能会想到只去差值最大的k个段即可,但是想到相临的段可以进行合并,这样由合并带来的损失可能小于抛弃一段带来的损失,因此不能简单的取最大的k个,如:
"[1, 5], [2, 6], [5, 7]", k=2,如果直接取[1, 5], [2, 6]其和为:8,但是如果把[2, 6], [5, 7]合并得[2, 7],然后取[1, 5], [2, 7]其和为:9

相关操作如下

  1. 求出给出序列中所有上升段,数组profits,其由pair组成,分别为段的起点和终点。
  2. k ≥ profits.length(),到第6步;若k < profits.length()到第3步。
  3. 找出profits中差值最小的段,记为min_seg,记损失为:min_lost。
  4. 找出profits中,前后合并损失最小的段min_merge_seg,记损损失为:min_merge_lost。
  5. 比较min_lost和min_merge_lost,如果min_lost <= min_merge_lost,在profitsk 移除min_seg;反之,合并min_merge_seg前后元素。转第2步。
  6. 取得当前profits中元素差值合,即为最大k次交易获得的最大利益。

相关代码如下(请用c++14编译):

#include <iostream>#include <vector>#include <iterator>#include <numeric>using namespace std;class Solution {public:    int maxProfit(int k, vector<int>& prices) {        if (prices.size() <= 1 || k < 1) {            return 0;        }        vector<pair<int, int>> profits;        int lower = prices[0];        int higher;        bool flag = false;        vector<int>::iterator iter;        // Get all ascend sequence begin and end point.        for (iter = prices.begin(); iter != prices.end(); ++iter) {            if (*(iter - 1) > *iter) {                if (flag) {                    profits.emplace_back(lower, higher);                }                lower = *iter;                flag = false;            } else if (*(iter - 1) <= *iter) {                flag = true;                higher = *iter;            }        }        if (flag) {            profits.emplace_back(lower, higher);        }        // Make the number of the elements in profits less than k        while (profits.size() > k) {            // Remove the least profit one, resort to deleting the minimum            // element or merge the adjacent elements            removeLeast(profits);        }        // Get the sum of the profit as the result        return accumulate(begin(profits), end(profits), 0,                [](int sum, pair<int, int>& profit) {                    return sum + (profit.second - profit.first);                });    }    /**     * Compare removing minimum profit element with merging two adjacent     * elements and get a better strategy     */    void removeLeast(vector<pair<int, int>>& profits) {        // Get the minimum profit one        auto min_tran = min_element(begin(profits), end(profits),                [](pair<int, int>& op1, pair<int, int>& op2) {                    return (op1.second - op1.first) < (op2.second - op2.first);                });        // Get the minimum profit        int min_tran_value = (*min_tran).second - (*min_tran).first;        vector<pair<int, int>>::iterator min_iter;        int min_value = min_tran_value;        int tmp;        vector<pair<int, int>>::iterator iter;        // Get the minimum lost by merge the adjancent two elements        for (iter = begin(profits) + 1; iter != end(profits); ++iter) {            tmp = getMergeReduce(*(iter - 1), *iter);            if (tmp < min_value) {                min_iter = iter;                min_value = tmp;            }        }        // Compare the simply remove element lost with merge adjacent elements        // and get the better strategy        if (min_tran_value <= min_value) {            profits.erase(min_tran);        } else {            (*min_iter).first = (*(min_iter - 1)).first;            profits.erase(min_iter - 1);        }    }    /**     * Calculate the lost by merging the adjacent two elements     */    int getMergeReduce(pair<int, int>& op1, pair<int, int>& op2) {        int before = (op1.second - op1.first) + (op2.second - op2.first);        int after = op2.second - op1.first;        return before - after;    }};int main(int argc, char* argv[]) {    Solution so;    int k;    cout << "Please input k: ";    cin >> k;    cout << "Please input element:\n";    vector<int> prices;    copy(istream_iterator<int>(cin), istream_iterator<int>(),            back_inserter(prices));    int re = so.maxProfit(k, prices);    cout << "re: " << re << endl;    return 0;}
Test: Please input k: 2Please input element:1 5 2 6 5 7re: 9
0 0
原创粉丝点击