第444场周赛——移除最小数对使数组有序 II
题目
题解
题目描述每次选择需要找到最小的相邻两个元素的和,如果相同选择最左边的一对,那我们可以拿个set来记录所有的相邻元素和以及他们的下标(拿左边元素的下标记录),然后每次操作就是找到一对,将这对两个数的和放在他俩左边元素下标中,删除右边元素,这个时候我们会受影响的只有左边元素的上一个,右边元素的下一个,以及他们两个本身,所以我们需要修改他们和上个元素的和放入set中,修改他们和下个元素的和放入set中。那我们该如何获取当前位置的上一个未删除下标和下一个未删除的下标呢。我们可以拿一个set存储,如果已被删除直接移除,然后通过迭代器指引找到上下位置的下标。
参考代码
class Solution {
public:
    int minimumPairRemoval(vector<int>& nums) {
        int n = nums.size();
        set<pair<long long, int>> pairs;
        int dec = 0;
        for(int i = 0; i < n - 1; i++) {
            int x = nums[i], y = nums[i + 1];
            if(x > y) dec++;
            pairs.emplace(x + y, i);
        }
        set<int> idx;
        for(int i = 0; i < n; i++) idx.insert(i);
        vector<long long> a(nums.begin(), nums.end());  //不复制一份可能会爆int
        int ans = 0;
        while(dec > 0) {
            ans++;
            auto [s, i] = *pairs.begin();
            pairs.erase(pairs.begin());
            auto it = idx.lower_bound(i);
            auto nxt_it = next(it);
            int nxt = *nxt_it;
            dec -= a[i] > a[nxt];
            if(it != idx.begin()) {
                int pre = *prev(it);
                dec -= a[pre] > a[i];
                dec += a[pre] > s;
                pairs.erase({a[pre] + a[i], pre});
                pairs.emplace(a[pre] + s, pre);
            }
            auto nxt2_it = next(nxt_it);
            if(nxt2_it != idx.end()) {
                int nxt2 = *nxt2_it;
                dec -= a[nxt] > a[nxt2];
                dec += s > a[nxt2];
                pairs.erase({a[nxt] + a[nxt2], nxt});
                pairs.emplace(s + a[nxt2], i);
            }
            a[i] = s;
            idx.erase(nxt);            
        }
        return ans;
    }
};

                
            
        
浙公网安备 33010602011771号