忙碌的一天,到待产的病房啦,明天迎接儿子的诞生,尽量不耽误作业,21:11,加油!!
435. 无重叠区间
我按思路写的东西似乎过于繁琐,不过也算是憋出来了,写下来。
class Solution {
public:
static bool cmp(const vector<int>& a,const vector<int>& b){
if(a[1] == b[1])return (a[0] < b[0]);
return (a[1] < b[1]);
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(),intervals.end(),cmp);
int chongdie = 0;
int feijiaocha = 1;
for(int i = 1;i < intervals.size();i++){
if(intervals[i-1][1] > intervals[i][0]){
chongdie++;
intervals[i][1] = min(intervals[i][1],intervals[i-1][1]);
}else{
feijiaocha++;
}
}
return(intervals.size() - feijiaocha);
}
};
随想录的写法更加精简,还是以右端为排列来做。
count就是非重叠的部分。
class Solution {
public:
// 按照区间右边界排序
static bool cmp (const vector<int>& a, const vector<int>& b) {
return a[1] < b[1];
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if (intervals.size() == 0) return 0;
sort(intervals.begin(), intervals.end(), cmp);
int count = 1; // 记录非交叉区间的个数
int end = intervals[0][1]; // 记录区间分割点
for (int i = 1; i < intervals.size(); i++) {
if (end <= intervals[i][0]) {
end = intervals[i][1];
count++;
}
}
return intervals.size() - count;
}
};
763.划分字母区间
我写的长这样,主要问题在于需要有max_node,因为max_node在不断地增大,除非遇到的都是重复的字母,直至max_node 和 i相同,说明缘分到了。随想录的基本一致,然后就是这个+1,画一下过程就可以想到。
class Solution {
public:
vector<int> partitionLabels(string s) {
int hash[27] = {0};
vector<int> result;
result.clear();
int last_node = 0;
int max_node = 0;
for(int i=0;i< s.size();i++){
hash[s[i] - 'a'] = i;
//实际上把s里,a~z的最后一次出现的值存储到hash里
}
for(int i = 0; i < s.size();i++){
max_node = max(hash[s[i] - 'a'],max_node);
if(max_node == i){
result.push_back(i - last_node + 1);
last_node = i+1;
}
}
return result;
}
};
随想录补充的思路有点难想,大概是和435无重叠区间这题有点相似,把每个字母的起始和结束,做排序,然后在做重合判断。
class Solution {
public:
static bool cmp(vector<int> &a, vector<int> &b) {
return a[0] < b[0];
}
// 记录每个字母出现的区间
vector<vector<int>> countLabels(string s) {
vector<vector<int>> hash(26, vector<int>(2, INT_MIN));
vector<vector<int>> hash_filter;
for (int i = 0; i < s.size(); ++i) {
if (hash[s[i] - 'a'][0] == INT_MIN) {
hash[s[i] - 'a'][0] = i;
}
hash[s[i] - 'a'][1] = i;
}
// 去除字符串中未出现的字母所占用区间
for (int i = 0; i < hash.size(); ++i) {
if (hash[i][0] != INT_MIN) {
hash_filter.push_back(hash[i]);
}
}
return hash_filter;
}
vector<int> partitionLabels(string s) {
vector<int> res;
// 这一步得到的 hash 即为无重叠区间题意中的输入样例格式:区间列表
// 只不过现在我们要求的是区间分割点
vector<vector<int>> hash = countLabels(s);
// 按照左边界从小到大排序
sort(hash.begin(), hash.end(), cmp);
// 记录最大右边界
int rightBoard = hash[0][1];
int leftBoard = 0;
for (int i = 1; i < hash.size(); ++i) {
// 由于字符串一定能分割,因此,
// 一旦下一区间左边界大于当前右边界,即可认为出现分割点
if (hash[i][0] > rightBoard) {
res.push_back(rightBoard - leftBoard + 1);
leftBoard = hash[i][0];
}
rightBoard = max(rightBoard, hash[i][1]);
}
// 最右端
res.push_back(rightBoard - leftBoard + 1);
return res;
}
};
56. 合并区间
这题思路和前面的很相似,感觉以左边界排序好想一点,然后就是取最大取最小。
自己写的就很丑,因为不知道vector容器其他的玩法,看看随想录的。
看了随想录,更改了一下玩法。
class Solution {
public:
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]);
}
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>>result;
// vector<int>oneway;
sort(intervals.begin(),intervals.end(),cmp);
for(int i = 1;i<intervals.size();i++){
if(intervals[i-1][1] >= intervals[i][0]){
intervals[i][0] = min(intervals[i - 1][0],intervals[i][0]);
intervals[i][1] = max(intervals[i - 1][1],intervals[i][1]);
}
else{
// oneway.push_back(intervals[i-1][0]);
// oneway.push_back(intervals[i-1][1]);
// result.push_back(oneway);
result.push_back(intervals[i-1]);
// oneway.clear();
}
}
// oneway.push_back(intervals[intervals.size()-1][0]);
// oneway.push_back(intervals[intervals.size()-1][1]);
// result.push_back(oneway);
result.push_back(intervals[intervals.size()-1]);
return result;
}
};
随想录版:
他这个确实好巧妙啊,我先粘贴,再总结。
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> result;
if (intervals.size() == 0) return result; // 区间集合为空直接返回
// 排序的参数使用了lambda表达式
sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b){return a[0] < b[0];});
// 第一个区间就可以放进结果集里,后面如果重叠,在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;
}
};
先放进去,然后更改右边界。