LeetCode/排序贪心综合

1. 根据身高重建队列

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)
每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好有 ki 个身高大于或等于 hi 的人

class Solution {
public:
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(), [&](vector<int>& a, vector<int>& b) {
            return a[0] > b[0] || (a[0] == b[0] && a[1] < b[1]);
            //左边界降序,右边界升序
        });
        vector<vector<int>> ans;//维护一个比插入数大的数组
        for (vector<int>& person: people) {//从高往低
            ans.insert(ans.begin() + person[1], person);//插到指定位置,后面插入的不会影响前面
        }
        return ans;
    }
};

2. 无重叠区间

求最多无重叠区域(或最少删除次数)

//贪心选择最早结束的区间,以便后续更大选择范围
class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end(), [](const auto& u, const auto& v) {
            return u[1] < v[1]; });
        int n = intervals.size();
        int right = intervals[0][1];
        int ans = 1;
        for (int i = 1; i < n; ++i) {
            if (intervals[i][0] >= right) {//不重叠的话
                ++ans;
                right = intervals[i][1];//更新右边界
            }
        }
        return n - ans;
    }
};

3. 用最少数量的箭引爆气球

等价于选取点集,与每个区间交集至少为1

class Solution {
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        sort(points.begin(),points.end(),[&](vector<int>&a,vector<int>&b){
            return a[1]<b[1];
        });
        int target = points[0][1]; int res = 1;
        for(int i=1;i<points.size();i++)
            if(points[i][0]>target){//箭在左边界左方
                target = points[i][1];//再射一箭
                res++;
            }
        return res;
    }
};

4. 设置交集大小至少为2

5. 使数组最小的增量

给你一个整数数组 nums 。每次 move 操作将会选择任意一个满足 0 <= i < nums.length 的下标 i,并将 nums[i] 递增 1
返回使 nums 中的每个值都变成唯一的所需要的最少操作次数

//还可以用线性探测法,消耗空间
class Solution {
public:
    int minIncrementForUnique(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int move = 0;
        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] <= nums[i - 1]) {
                int pre = nums[i];
                nums[i] = nums[i - 1] + 1;
                move += nums[i] - pre;
            }
        }
        return move;
    }
};

6. 三角形的最大周长

//从后往前枚举最长边,然后贪心选择最近两个数作为边进行判断
class Solution {
public:
    int largestPerimeter(vector<int>& A) {
        sort(A.begin(), A.end());
        for (int i = A.size() - 1; i >= 2; --i) {
            if (A[i - 2] + A[i - 1] > A[i]) {
                return A[i - 2] + A[i - 1] + A[i];
            }
        }
        return 0;
    }
};

7. 删除一个元素使数组严格递增

class Solution {
public:
    bool canBeIncreasing(vector<int>& nums) {
        int cnt = 0;
        for(int i=1;i<nums.size()&&cnt<=1;i++){
            if(nums[i]>nums[i-1]) continue;
            cnt++;
            //判断要删除哪个
            if(i>1&&nums[i]<=nums[i-2])
                nums[i] = nums[i-1];
        }
        return cnt<2;
    }
};

8. 消灭怪物的最大数量

class Solution {
public:
    int eliminateMaximum(vector<int>& dist, vector<int>& speed) {
        int n = dist.size();
        vector<int> time;   // 每个怪物的最晚可被消灭时间
        for (int i = 0; i < n; ++i){
            time.push_back((dist[i] - 1) / speed[i]);
        }
        sort(time.begin(), time.end());
        for (int i = 0; i < n; ++i)
            if (time[i] < i) // 无法消灭该怪物,返回消灭的怪物数量
                return i;
        return n;
    }
};

9. 向数组中追加k个整数

//类似贪心最远距离,忽视相同元素
class Solution {
public:
    long long minimalKSum(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        long long sum = 0;
        for(int i=0;i<nums.size()&&k>=nums[i];i++){
            if(i>0&&nums[i]==nums[i-1]) continue;//跳过重复的
            sum+=nums[i];
            k = k+1;
        }
        return (long long)(1+k)*k/2 - sum;
    }
};

10. 最长数对链(与无重叠区域一致)

class Solution {
public:
    int findLongestChain(vector<vector<int>>& pairs) {
        int curr = INT_MIN, res = 0;
        sort(pairs.begin(), pairs.end(), [](const vector<int> &a, const vector<int> &b) {
            return a[1] < b[1];});
        for (auto &p : pairs) 
            if (curr < p[0]) {
                curr = p[1];
                res++;
            }
        return res;
    }
};
posted @ 2022-07-23 06:22  失控D大白兔  阅读(16)  评论(0编辑  收藏  举报