LeetCode 435 无重叠区间
题目链接:https://leetcode.cn/problems/non-overlapping-intervals/
思路:
我采用的思路和昨天的射箭题类似,在左边界进行排序。如果存在重叠区间,那么就记录下来,并且更新右边界
代码:
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
int result = 0;
if(intervals.size()==0||intervals.size()==1) return result;
sort(intervals.begin(),intervals.end(),cmp);
for(int i = 1;i<intervals.size();i++)
{
if(intervals[i][0]>=intervals[i-1][1])
continue;
else
{
intervals[i][1] = min(intervals[i][1],intervals[i-1][1]);
result++;
}
}
return result;
}
static bool cmp(const vector<int>&a,const vector<int>&b)
{
if(a[0]==b[0])
return a[1]<b[1];
return a[0]<b[0];
}
};
总结
相对简单
LeetCode 763 划分字母区间
题目链接:https://leetcode.cn/problems/partition-labels/
思路:
在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。
可以分为如下两步:
统计每一个字符最后出现的位置
从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点
代码:
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;
// 通过每个字母的最远下标划分区间
int left = 0;
int right = 0;
vector<int>result;
for(int i = 0;i<s.size();i++)
{
right = max(right,hash[s[i]-'a']);
if(i==right) // 说明此时已经遍历到了最远处,i前面的元素都只会在该区间内出现
{
result.push_back(right-left+1);
left = i+1; // 更新区间的起点,终点会自动在下一个循环中更新
}
}
return result;
}
};
总结
第一次遇到这种题目,一开始有点懵,听完讲解之后豁然开朗。
LeetCode 56 合并区间
题目链接:https://leetcode.cn/problems/merge-intervals/
思路:
重叠区间的题目,自己的想法是按左边界排序。
如果发现重叠,那么就同时更新左边界和右边界。这样操作的话,相对复杂。卡哥的思路是排序好了之后将第一个数组放入结果集后,比较后面数组的左边界和第一个数组的右边界。如果左边界小于右边界,那么必然重叠,此时只需要更新结果集里元素的右边界即可。
代码:
自写
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>>result;
if(intervals.size()==1) return intervals;
sort(intervals.begin(),intervals.end(),cmp);
for(int i =1;i<intervals.size();i++)
{
if(intervals[i][0]>intervals[i-1][1])
result.push_back(intervals[i-1]);
else
{
intervals[i][0] = min(intervals[i-1][0],intervals[i][0]);
intervals[i][1] = max(intervals[i-1][1],intervals[i][1]);
}
if(i==intervals.size()-1)
result.push_back(intervals[i]);
}
return result;
}
static bool cmp(const vector<int>&a,const vector<int>&b)
{
if(a[0]==b[0])
return a[1]<b[1];
return a[0]<b[0];
}
};
优化代码
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>>result;
if(intervals.size()==1) return intervals;
sort(intervals.begin(),intervals.end(),cmp);
// 第一个区间就可以放进结果集里,后面如果重叠,在result上直接合并
result.push_back(intervals[0]);
for (int i = 1; i < intervals.size(); i++) {
if (result.back()[1] >= intervals[i][0]) { // 发现重叠区间
// 合并区间,只更新右边界就好,因为result.back()的左边界一定是最小值,因为我们按照左边界排序的
result.back()[1] = max(result.back()[1], intervals[i][1]);
} else {
result.push_back(intervals[i]); // 区间不重叠
}
}
return result;
}
static bool cmp(const vector<int>&a,const vector<int>&b)
{
if(a[0]==b[0])
return a[1]<b[1];
return a[0]<b[0];
}
};
总结
相对简单。
今日总结:
今天就划分字母区间如何找分割点没有想到,其余题目相对简单。