代码随想录算法训练营第36天|435. 无重叠区间,763.划分字母区间,56. 合并区间
435. 无重叠区间
题目链接:435. 无重叠区间,难度:中等
【实现代码】
class Solution {
public:
static bool cmp(vector<int>& interval1, vector<int>& interval2) {
return interval1[1] < interval2[1];
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(), cmp);
// for (int i = 0; i < intervals.size(); i++) {
// cout << intervals[i][0] << " " <<intervals[i][1] << endl;
// }
int result = 0;
for (int i = 1; i < intervals.size(); i++) {
if (intervals[i][0] < intervals[i - 1][1]) {
result++;
intervals[i][1] = intervals[i - 1][1];
// min(intervals[i - 1][1], intervals[i][0]);
}
}
return result;
}
};
【解题思路】
这一题和452. 用最少数量的箭引爆气球很像,只是这里是要求删除重叠的区间。
首先是对数据进行排序,按照左值或者右值都可以,这里按照右值进行升序排列,当前的左值小于前一个的右值时,说明二者有重叠,则应该删除当前的区间,并且更新当前区间的右值为二者的最小值(因为并没有实际的将元素删除)
763. 划分字母区间
题目链接:763. 划分字母区间,难度:中等
【实现代码】
class Solution {
public:
vector<int> partitionLabels(string s) {
vector<int> result;
vector<int> hash(26, 0);
for (int i = 0; i < s.size(); i++) {
hash[s[i] - 'a'] = i;
}
int right = -1;
int left = 0;
for (int i = 0; i < s.size(); i++) {
if (hash[s[i] - 'a'] > right) {
right = hash[s[i] - 'a'];
}
if (i == right) {
result.push_back(i - left + 1);
left = i + 1;
}
}
return result;
}
};
【解题思路】
我本意是想找当前字母在字符串中的最大索引,再找区间内其他字母的最大索引。费时费力!
使用hash数组记录每一个字母存在的最大索引,当前索引等于其经过的字母所在索引的最大值时,则开始划分区间。
56. 合并区间
题目链接:56. 合并区间,难度:中等
【实现代码】
class Solution {
public:
static bool cmp(vector<int>& interval1, vector<int>& interval2) {
return interval1[0] < interval2[0];
}
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> 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(intervals[i][1], result.back()[1]);
} else {
result.push_back(intervals[i]);
}
}
return result;
}
};
【解题思路】
本题目是将所有重叠的区间合并。和今天的第一题很像。
首先是对数据进行排序,我这里按照左值升序排列。
因为是要合并区间那么就需要考虑已经存入的区间和当前区间的关系,所以是将第一个元素存起来,再进行依次比较。当重叠时则更新范围,否则直接压入新的区间范围。