435. 无重叠区间
解题思路
本题和射气球那题是一模一样的,同样的判断下一个区间是否还是重叠,也是把i区间的右区间和i-1右区间取最小值即可
class Solution {
public:
static bool cmp(const vector<int>& a , const vector<int>& b)
{
return a[0] < b[0]; //按照左边界来排序
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
int count = 0;
sort(intervals.begin(),intervals.end(),cmp);
for(int i =1 ; i<intervals.size();i++)
{
if(intervals[i][0]< intervals[i-1][1]) //这个区间的左区间小于上个区间的右区间,则要删除一个区间
{
count++;
intervals[i][1] = min(intervals[i][1],intervals[i-1][1]); //更新这个区间的右区间,用来判断下一个区间是否还是重叠
}
}
return count;
}
};
时间复杂度:O(nlog n) ,有一个快排
空间复杂度:O(n),有一个快排,最差情况(倒序)时,需要n次递归调用。因此确实需要O(n)的栈空间
763.划分字母区间
解题思路
思路:只要我们包含了a,那么就必须将区间长度一直延伸到最后一个a的位置
在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。
可以分为如下两步:
- 统计每一个字符最后出现的位置
- 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点
class Solution {
public:
vector<int> partitionLabels(string s) {
int hash[27] = {0} ;
for(int i =0 ;i < s.size() ; i++)
{
hash[s[i] -'a' ] = i; //遍历一遍数组,在对应字母的位置把下标更新,当字母最后一次更细时,就是最后位置的下标
}
vector<int> result ;
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 =right + 1 ; //更新左区间
}
}
return result;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1),使用的hash数组是固定大小
56. 合并区间
解题思路
和之前的重叠区间的思路是一模一样的,只是处理逻辑不同而已,也是尽量让重叠区间在一起
如果 intervals[i][0] <= intervals[i - 1][1]
即intervals[i]的左边界 <= intervals[i - 1]的右边界,则一定有重叠。(本题相邻区间也算重贴,所以是<=)
有重叠就直接进行融合即可
class Solution {
public:
static bool cmp(const vector<int>& a , const vector<int>& b)
{
return a[0] < b[0] ; //按左区间进行排列
}
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> result;
if(intervals.size()==0) return result; //输入为空
sort(intervals.begin(),intervals.end(),cmp);
result.push_back(intervals[0]);
for(int i =1 ; i< intervals.size() ; i++)
{
if(intervals[i][0]<=result.back()[1]) //我们只需要和结果集的最后一个去比较,发现重叠直接改右边界的值即可
result.back()[1] = max(result.back()[1],intervals[i][1]);
else
result.push_back(intervals[i]); //没有重叠,直接加入结果集
}
return result;
}
};
这里巧妙的一个点,就是直接修改结果中的最后一个元素的右边界,节省了一些时间和空间,因为结果集中最后一个元素的左边界肯定是小的(已经排序过了)
- 时间复杂度: O(nlogn)
- 空间复杂度: O(logn),排序需要的空间开销
收获
重叠区间类的题目,基本都是一样的,还是比较简单的