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;
}
};