• 【算法】重载sort的cmp的题


    1 406根据身高重建队列

    406. 根据身高重建队列

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

    请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

    这个题需要重载sort函数中的cmp。

    (1)当身高相同时,ki小的在前面,即身高相同时,ki升序排序;

    (2)身高不同时,个子高的人在前面,即按个子降序排序。

    (3)排序完后,需要得到每个人在队伍中的位置,即按照ki插入。

    1. class Solution {
    2. public:
    3. // 重载排序函数
    4. static bool cmp(const vector<int>& a, const vector<int>& b) {
    5. // 身高相同,人数少的在前面,即升序
    6. if (a[0] == b[0]) {
    7. return a[1] < b[1];
    8. }
    9. // 身高不同,高个子人在前面
    10. return a[0] > b[0];
    11. }
    12. vectorint>> reconstructQueue(vectorint>>& people) {
    13. sort(people.begin(), people.end(), cmp);
    14. listint>> res;
    15. for (int i = 0; i < people.size(); i++) {
    16. // 拿到位置
    17. int position = people[i][1];
    18. auto it = res.begin();
    19. // 找到插入的位置
    20. while (position--) {
    21. it++;
    22. }
    23. res.insert(it, people[i]);
    24. }
    25. return vectorint>>(res.begin(), res.end());
    26. }
    27. };

    2 用最少数量的箭引爆气球

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

    有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。

    一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足  xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

    给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。

    这个题需要重载sort函数中的cmp。

    (1)先对气球按起始位置升序排序(终止位置排序也行,起始位置好理解);

    (2)没有交集的气球,直接射一支➹即可;

    (3)有交集的气球,更新右边界,注意:右边界是取两者的较小者,等到下次再和下一个气球判断,无交集,射出一支箭;有交集继续更新。

    1. class Solution {
    2. public:
    3. // 重载排序
    4. static bool cmp(const vector<int>& a, const vector<int>& b) {
    5. // 按照起始位置升序排序
    6. return a[0] < b[0];
    7. }
    8. int findMinArrowShots(vectorint>>& points) {
    9. sort(points.begin(), points.end(), cmp);
    10. int res = 1; // 至少需要一支箭
    11. int end = points[0][1];
    12. for (int i = 1; i < points.size(); i++) {
    13. // 没有交集
    14. if (points[i][0] > end) {
    15. res++;
    16. end = points[i][1];
    17. } else {
    18. end = min(end, points[i][1]);
    19. }
    20. }
    21. return res;
    22. }
    23. };

    3 无重叠区间

    435. 无重叠区间

    给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。

    (1)本题同样需要重载sort的cmp,这里使用lambda表达式

    (2)这里按照终止位置升序排序,即终止位置小的在前面,这里为什么不按照起始位置升序排序呢?因为终止位置和是下一个起始位置可能重合的区域;

    (3)统计重叠区间个数,更新右边界,注意:这里的右边界是取两者的较小者

    1. class Solution {
    2. public:
    3. int eraseOverlapIntervals(vectorint>>& intervals) {
    4. // 使用lambda表达式
    5. sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b){
    6. // 按照终止位置升序排序
    7. return a[1] < b[1];
    8. });
    9. int res = 0; // 重叠
    10. int end = intervals[0][1];
    11. for (int i = 1; i < intervals.size(); i++) {
    12. // 重叠
    13. if (end > intervals[i][0]) {
    14. res++;
    15. end = min(end, intervals[i][1]);
    16. } else {
    17. end = intervals[i][1];
    18. }
    19. }
    20. return res;
    21. }
    22. };

    4 合并区间

    56. 合并区间

    以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

    (1)按照起始位置升序排序;

    (2)判断第i个区间和第i-1个区间是否有重合,如果有重合,则合并,并更新右边界,注意:这里的右边界是取两者的较大者;

    (3)这里还需要对最后一个区间进行判断。

    1. class Solution {
    2. public:
    3. static bool cmp(vector<int>& a, vector<int>& b) {
    4. // 按照起始位置升序排序
    5. return a[0] < b[0];
    6. }
    7. vectorint>> merge(vectorint>>& intervals) {
    8. vectorint>> res;
    9. if (intervals.size() == 0) {
    10. return res;
    11. }
    12. // 排序
    13. sort(intervals.begin(), intervals.end(), cmp);
    14. // 标记最后一个区间有没有合并
    15. bool flag = false;
    16. int len = intervals.size();
    17. for (int i = 1; i < len; i++) {
    18. int start = intervals[i - 1][0]; // i-1的左边界
    19. int end = intervals[i - 1][1]; // i-1的右边界
    20. // 可以合并
    21. while (i < len && intervals[i][0] <= end) {
    22. end = max(end, intervals[i][1]); // 更新右边界
    23. // 最后一个区间
    24. if (i == len - 1) {
    25. flag = true;
    26. }
    27. i++;
    28. }
    29. res.push_back({start, end});
    30. }
    31. // 如果最后一个区间没有被合并,将其加入到res中
    32. if (flag == false) {
    33. res.push_back({intervals[len - 1][0], intervals[len - 1][1]});
    34. }
    35. return res;
    36. }
    37. };

    感受:这类题在最开始接触的时候,无从下手,只是有一个感觉,可能要按左或者按右排序,具体怎么排,还真想不到,做了一两道之后,慢慢有点感觉了。

  • 相关阅读:
    Flutter高仿微信-第57篇-添加好友
    FLStudio2023水果中文版本使用操作心得与技巧
    驱动开发:内核字符串拷贝与比较
    构建Docker基础镜像(ubuntu20.04+python3.9.10+pytorch-gpu-cuda11.8)
    ASP.NET Core 6框架揭秘实例演示[07]:文件系统
    分布式环境下的数据同步
    SpringBoot整合EasyExcel
    数据集笔记:旧金山共享单车OD数据
    HIVE多维分析函数:grouping sets、cube、rollup
    0基础python全栈教程前言,0基础学习python难不难
  • 原文地址:https://blog.csdn.net/Zhouzi_heng/article/details/126680202