(36/60)无重叠区间、划分字母区间、合并区间
无重叠区间
leetcode:435. 无重叠区间
贪心法
思路
去掉最少的区间数就是最少重叠区间对的个数。(成对的算,因为一对里面需要去掉一个)
类似射气球的处理方式。
左边界法:
-
按左边界从小到大排序。
-
遍历每个元素。取当前元素右边界为right判断是否重叠。
如果
[i]right > [i+1]left
,重叠,再判断是否[i]right > [i+1]right
,如果是,右边界更新。(总是更新为一对重叠区间里最小的)重叠统一i++(继续判断下一个),count++(重叠区间对多一个)。
复杂度分析
时间复杂度:O(NlogN)。
空间复杂度:O(logN)。(排序)
注意点
略
代码实现
左区间排序法:
class Solution { public: // 计算重叠区间个数 static bool cmp(vector<int>& a,vector<int>& b){ return a[0] < b[0]; } int eraseOverlapIntervals(vector<vector<int>>& intervals) { sort(intervals.begin(),intervals.end(),cmp); int count = 0; for(int i = 0;i < intervals.size();i++){ int right = intervals[i][1]; while(i < intervals.size() - 1 && right > intervals[i + 1][0] ){ if(right > intervals[i+1][1]) right = intervals[i + 1][1]; count++; i++; } } return count; } };
划分字母区间
leetcode:763. 划分字母区间
贪心法
思路
-
遍历一遍s,建立出现最远下标映射表(数组)
-
根据区间遍历,遍历过程中更新区间右边界为区间内最远下标,
如果遍历到了区间右边界,说明已经实现了区间字符只出现在区间内,收获结果(区间长度)
复杂度分析
时间复杂度:O(N)。
空间复杂度:O(1)。26个字母的映射数组。
注意点
略
代码实现
class Solution { public: // 1. 遍历一遍s,建立出现最远下标映射表(数组) // 2. 根据区间遍历,遍历过程中更新区间右边界为区间内最远下标, // 如果遍历到了区间右边界,说明已经实现了区间字符只出现在区间内,收获结果(区间长度) vector<int> partitionLabels(string s) { vector<int> result; int hash[27] = {0}; for(int i = 0;i < s.size();i++) hash[s[i] - 'a'] = i; int left = 0; int right = 0; for(int i = 0;i < s.size();i++){ right = max(right,hash[s[i] - 'a']); // 右边界更新为区间内元素出现最远下标 if(i == right) { // 到达区间最远下标 result.push_back(right - left + 1); // 收获长度 left = i + 1; // 更新left } } return result; } };
合并区间
leetcode:56. 合并区间
贪心法
思路
和射气球、无重叠区间类似,只是右边界每次更新为最大值。
-
按左边界从小到大排序。
-
遍历记录当前元素左右边界。
循环处理
right > intervals[i+1][0]
,重叠的情况,每次更新right为两者最大值。直到不再重叠时,收获left、right结果。
复杂度分析
时间复杂度:O(NlogN)。排序
空间复杂度:O(N)。(最差情况下N个元素都不重叠,结果集N个元素)
注意点
略
代码实现
class Solution { public: // 排序 // 如果有重叠,更新 static bool cmp(vector<int>& a,vector<int>& b){ return a[0] < b[0]; } vector<vector<int>> merge(vector<vector<int>>& intervals) { sort(intervals.begin(),intervals.end(),cmp); vector<vector<int>> result; vector<int> temp; int left = 0; int right = 0; for(int i = 0;i < intervals.size();i++){ temp.clear(); left = intervals[i][0]; right = intervals[i][1]; while(i < intervals.size() - 1 && right >= intervals[i + 1][0]){ right = max(right,intervals[i+1][1]); i++; } temp.push_back(left); temp.push_back(right); result.push_back(temp); } return result; } };
分类:
算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通