• 算法学习笔记(7.4)-贪心算法(区间调度问题)


    目录

    ##什么是区间调度问题

    ##贪心解法

     ##具体的例题示例讲解

    ##452. 用最少数量的箭引爆气球 - 力扣(LeetCode)

    ##435. 无重叠区间 - 力扣(LeetCode)

    ##56. 合并区间 - 力扣(LeetCode)


    ##什么是区间调度问题

    区间调度问题是一个经典的贪心算法问题:

    通常描述为:给定一组活动,每个活动都有一个开始时间和结束时间。只有一个活动能在同一时间段内进行。目标是找到最大数量的互不相交的活动。

    ##贪心解法

    1. 从区间集合 intvs 中选择一个区间 x,这个 x 是在当前所有区间中结束最早的(开始最早)。
    2. 把所有与 x 区间相交的区间从区间集合 intvs 中删除。
    3. 重复步骤 1 和 2,直到 intvs 为空为止。之前选出的那些 x 就是最大不相交子集。

     ##具体的例题示例讲解

    ##452. 用最少数量的箭引爆气球 - 力扣(LeetCode)

    ##思路

    1.第一步按照最先开始时间排序(结束最早)

    2.然后开始遍历数组,找到有交集的区间,进行修改

    3.将当前位置的结束区间和上一个跟当前有交集的结束区间的最小值赋值给当前位置的结束区间

    4.样例解释{first:[1,4],[2,3],result:[1,4],[2,3]; second:[1,5],[2,6],result:[1,5],[2,5],third:[1,3],[2,3],result:[1,3],[2,3]}

    5.解释以下second:

    当然下面一个气球有可能和上面两个气球都重合,如果只和上面一个气球重合而不和上上面气球重合的话,那么还需要额外的一支箭去引爆。

    为了实现判断,当两支气球重合时,我们可以把右边界缩小为两个气球右边界较小的一个值(因为此时新气球的左边界一定大于等于上面两个气球的左边界,所以不用判断),如果新气球左边界小于上面气球的右边界,那么就不需要额外的箭就能引爆。

    ##代码示例

    1. //c++代码示例
    2. class Solution {
    3. public:
    4. int findMinArrowShots(vectorint>>& points) {
    5. if (points.size() == 0)
    6. {
    7. return 0 ;
    8. }
    9. sort(points.begin(),points.end(),[](const vector<int>& a,const vector<int>& b)
    10. {
    11. return a[0] < b[0] ;
    12. }) ;
    13. int ans = 1 ;
    14. for (int i = 1 ; i < points.size() ; i++)
    15. {
    16. if (points[i][0] <= points[i-1][1])
    17. {
    18. points[i][1] = min(points[i][1],points[i-1][1]) ;
    19. }
    20. else
    21. {
    22. ans++ ;
    23. }
    24. }
    25. return ans ;
    26. }
    27. };
    1. //python代码示例
    2. class Solution:
    3. def findMinArrowShots(self, points: List[List[int]]) -> int:
    4. points.sort(key = lambda x : x[0] ,reverse =False)
    5. if len(points) == 0 :
    6. return 0
    7. ans = 1
    8. for i in range(1,len(points)) :
    9. if (points[i][0] <= points[i-1][1]) :
    10. points[i][1] = min(points[i][1],points[i-1][1])
    11. else :
    12. ans += 1
    13. return ans

    ##435. 无重叠区间 - 力扣(LeetCode)

    ##思路

    跟上一个题目的思路一样

    具体的细节:当本区间左边界比上一个区间右边界小的时候我们就需要去删除了。删除在代码上只需要将此区间右边界设置为此区间与上一个区间中的较小值就可以了。如果此区间左边界大于等于上一个区间右边界,那么就证明两个区间没有重合,不需要进行操作。

    ##代码示例

    1. //c++代码示例
    2. class Solution {
    3. public:
    4. int eraseOverlapIntervals(vectorint>>& intervals) {
    5. sort(intervals.begin(),intervals.end(),[](const vector<int>& a,const vector<int>& b)
    6. {
    7. return a[0] < b[0] ;
    8. }) ;
    9. int ans = 0 ;
    10. for (int i = 1 ; i < intervals.size() ; i++)
    11. {
    12. if (intervals[i][0] < intervals[i-1][1])
    13. {
    14. intervals[i][1] = min(intervals[i-1][1],intervals[i][1]) ;
    15. ans++ ;
    16. }
    17. }
    18. return ans ;
    19. }
    20. };
    1. //python代码示例
    2. class Solution:
    3. def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
    4. intervals.sort(key = lambda x : x[0] ,reverse = False)
    5. if (len(intervals) == 0) :
    6. return 0
    7. ans = 0
    8. for i in range(1,len(intervals)) :
    9. if (intervals[i][0] < intervals[i-1][1]) :
    10. intervals[i][1] = min(intervals[i][1],intervals[i-1][1])
    11. ans += 1
    12. return ans

    ##56. 合并区间 - 力扣(LeetCode)

    ##思路

    先进行排序,然后用此区间左边界与上一个区间右边界进行比较,如果满足重叠,则进行记录。

    ##代码示例

    1. //c++代码示例
    2. class Solution {
    3. public:
    4. vectorint>> merge(vectorint>>& intervals) {
    5. vectorint>> ans ;
    6. sort(intervals.begin(),intervals.end(),[](const vector<int>& a,const vector<int>& b)
    7. {
    8. return a[0] < b[0] ;
    9. }) ;
    10. for (int i = 0 ; i < intervals.size() ; i++)
    11. {
    12. if (!ans.empty() && intervals[i][0] <= ans[ans.size()-1][1])
    13. {
    14. ans[ans.size()-1] = {min(ans[ans.size()-1][0],intervals[i][0]),max(ans[ans.size()-1][1],intervals[i][1])} ;
    15. }
    16. else
    17. {
    18. ans.push_back({intervals[i][0],intervals[i][1]}) ;
    19. }
    20. }
    21. return ans ;
    22. }
    23. };
    1. //python代码示例
    2. class Solution:
    3. def merge(self, intervals: List[List[int]]) -> List[List[int]]:
    4. ans = []
    5. intervals.sort(key=lambda x: x[0])
    6. for i in range(len(intervals)):
    7. if ans and intervals[i][0] <= ans[-1][1]:
    8. ans[-1] = [min(ans[-1][0], intervals[i][0]), max(ans[-1][1], intervals[i][1])]
    9. else:
    10. ans.append([intervals[i][0], intervals[i][1]])
    11. return ans
  • 相关阅读:
    Android 系统启动 <zygote 进程> 笔记【2】
    Oracle数据库时区、系统时间的检查与修改
    【深度学习】深度学习中模型计算量(FLOPs)和参数量(Params)等的理解以及四种在python应用的计算方法总结
    关于el-date-picker组件修改输入框以及下拉框的样式
    AIOps指标异常检测之无监督算法
    Nginx网络服务之监控模块
    Java泛型理解
    面试常见问题丨深入解析Spring中Bean的整个初始化过程
    ios CI/CD 持续集成 组件化专题一 iOS 将图片打包成bundle
    JS逆向爬虫案例分享(RSA非对称加密)
  • 原文地址:https://blog.csdn.net/2301_76874968/article/details/139401847