leetcode数组刷题(七)——区间集合处理
56、合并区间
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
多区间求并集,只需要按照区间的三类情况进行讨论即可。
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
if(intervals.size()==0) return {};
vector<vector<int>> results;
sort(intervals.begin(),intervals.end());
results.push_back(intervals[0]);
for(int i=1;i<intervals.size();++i){
//int min = intervals[i][0];
//int max = intervals[i][1];
if(intervals[i][0]>results.back()[1]) results.push_back(intervals[i]);
else if(intervals[i][0]<=results.back()[1]){
if(intervals[i][1]>=results.back()[1]){
results.back()[1] = intervals[i][1];
}
}
}
return results;
}
};
57、插入区间
给你一个 无重叠的 ,按照区间起始端点排序的区间列表
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
我自己用的就是分情况讨论的方法,用时击败99%,但是内存有点大,毕竟代码的变量有点多。测试了几次才通过的,原因第一个是for内嵌for不能用break打断,直接return,不然还会继续外循环。第二个原因是情况分类讨论不够全,之前一直忽视了continue的分类讨论,就是新的区间的左右范围都可能大于已有区间的范围的情况,需要另外考虑。
class Solution {
public:
vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
if(intervals.size()==0) return {newInterval};
vector<vector<int>> results;
vector<int> temp = intervals[0];
for(int i=0;i<intervals.size();++i){
if(newInterval[0]>intervals[i][1]){
if(i==intervals.size()-1){
results.push_back(intervals[i]);
results.push_back(newInterval);
return results;判断区间大于已有区间
}
else{
results.push_back(intervals[i]);
continue;//找到区间左数插入的地方
}
}
else if(newInterval[0]<=intervals[i][1]){
//if(newInterval[0]>=intervals[i][0]){
temp[0] = min(intervals[i][0],newInterval[0]);
for(int j=i;j<intervals.size();++j){
if(newInterval[1]>intervals[j][1]){
if(j==intervals.size()-1){
temp[1] = newInterval[1];//判断区间大于已有区间
results.push_back(temp);
return results;
}
else continue;//区间右数
}
if(newInterval[1]<=intervals[j][1]){
if(newInterval[1]>=intervals[j][0]) {
temp[1] = intervals[j][1];
results.push_back(temp);
for(int k=j+1;k<intervals.size();++k){
results.push_back(intervals[k]);
//break;会继续外层循环有误,答案重复
}
return results;
}
else{
temp[1] = newInterval[1];
results.push_back(temp);
for(int k=j;k<intervals.size();++k){
results.push_back(intervals[k]);
//break;会继续外层循环有误,答案重复
}
return results;
}
}
}
//}
}
}
return results;
}
};
官方的思路感觉更加清晰一些,就是直接分了三种情况,我是根据左右端点来考虑的,思路上烦琐了一些。
class Solution {
public:
vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
int left = newInterval[0];
int right = newInterval[1];
bool placed = false;
vector<vector<int>> ans;
for (const auto& interval: intervals) {
if (interval[0] > right) {
// 在插入区间的右侧且无交集
if (!placed) {
ans.push_back({left, right});
placed = true;
}
ans.push_back(interval);
}
else if (interval[1] < left) {
// 在插入区间的左侧且无交集
ans.push_back(interval);
}
else {
// 与插入区间有交集,计算它们的并集
left = min(left, interval[0]);
right = max(right, interval[1]);
}
}
if (!placed) {
ans.push_back({left, right});
}
return ans;
}
};
78、子集
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
这题参考组合的思路,同样采用回宿,一种是循环体,一种是分是否采用当下元素分类的官方思路,分为两种代码如下:
class Solution {
public:
vector<int> t;
vector<vector<int>> ans;
void dfs(vector<int>& nums, int cur) {
if (cur == nums.size()) return;
for(int i=cur;i<nums.size();i++){
t.push_back(nums[i]);
ans.push_back(t);
dfs(nums,i+1);
t.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
ans.push_back({});
dfs(nums,0);
return ans;
}
};
class Solution {
public:
vector<int> t;
vector<vector<int>> ans;
void dfs(int cur, vector<int>& nums) {
if (cur == nums.size()) {
ans.push_back(t);
return;
}
t.push_back(nums[cur]);
dfs(cur + 1, nums);
t.pop_back();
dfs(cur + 1, nums);
}
vector<vector<int>> subsets(vector<int>& nums) {
dfs(0, nums);
return ans;
}
};
90、子集 II
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
和所有问题一样的第二问,就是有重复元素,去重的语句可以参考组合或者全排列,其中代码一为参考组合,代码二为官方延续思路的需要加个bool判断变量,是否是第一个遇到的:
class Solution {
public:
vector<int> t;
vector<vector<int>> ans;
void dfs(vector<int>& nums, int cur) {
if (cur == nums.size()) return;
for(int i=cur;i<nums.size();i++){
if (i>cur && nums[i]==nums[i-1]) continue;
t.push_back(nums[i]);
ans.push_back(t);
dfs(nums,i+1);
t.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());
ans.push_back({});
dfs(nums,0);
return ans;
}
};
class Solution {
public:
vector<int> t;
vector<vector<int>> ans;
void dfs(bool choosePre, int cur, vector<int> &nums) {
if (cur == nums.size()) {
ans.push_back(t);
return;
}
dfs(false, cur + 1, nums);
if (!choosePre && cur > 0 && nums[cur - 1] == nums[cur]) {
return;
}
t.push_back(nums[cur]);
dfs(true, cur + 1, nums);
t.pop_back();
}
vector<vector<int>> subsetsWithDup(vector<int> &nums) {
sort(nums.begin(), nums.end());
dfs(false, 0, nums);
return ans;
}
};