[LeetCode] Set Intersection Size At Least Two 设置交集大小至少为2
An integer interval [a, b] (for integers a < b) is a set of all consecutive integers from a to b, including a and b.
Find the minimum size of a set S such that for every integer interval A in intervals, the intersection of S with A has size at least 2.
Example 1:
Input: intervals = [[1, 3], [1, 4], [2, 5], [3, 5]]
Output: 3
Explanation:
Consider the set S = {2, 3, 4}. For each interval, there are at least 2 elements from S in the interval.
Also, there isn't a smaller size set that fulfills the above condition.
Thus, we output the size of this set, which is 3.
Example 2:
Input: intervals = [[1, 2], [2, 3], [2, 4], [4, 5]]
Output: 5
Explanation:
An example of a minimum sized set is {1, 2, 3, 4, 5}.
Note:
intervalswill have length in range[1, 3000].intervals[i]will have length2, representing some integer interval.intervals[i][j]will be an integer in[0, 10^8].
这道题给了我们一些区间,让我们求一个集合S,使得S和每个区间的交集至少为2,即至少有两个相同的数字。博主最开始分析题目中的例子的时候,以为要求的集合S也必须是一个连续的区间,其实不需要的,离散的数字就可以了。比如如果区间是[1,3], [5,6]的话,那么返回的集合长度是4,而不是5。这道题可以是用贪婪算法来解,一般来说Hard的题目能用贪婪算法而不是DP解的是少之又少,这道题为我大Greedy算法正名了~!为了使得集合S中的数字尽可能的小,我们希望处理区间的时候从小区间开始,如果区间b完全覆盖了区间a,那么和区间a有两个相同数字的集合,一定和区间b也有两个相同数字。同样,我们不希望一会处理一个前面的区间,一会又处理一个很后面的区间,我们希望区间是有序的。那么如何给区间排序呢,是按起始位置排,还是按结束位置排,这里我们按结束位置从小往大排,当两个结束位置相同时,起始位置大的排前面先处理,这也符合我们先处理小区间的原则。那么遍历区间的时候,当前区间就和我们维护的集合S有三种情况:
1. 二者完全没有交集,这时候我们就需要从当前区间中取出两个数字加入集合S,取哪两个数呢?为了尽可能少使用数字,我们取当前区间中的最大两个数字,因为我们区间位置不断变大,所以取大的数字有更高的概率能和后面的区间有交集。
2. 二者有一个数字的交集,那么这个交集数字一定是区间的起始位置,那么我们需要从当前区间中再取一个数字加入集合S,根据上面的分析,我们取最大的那个数,即区间的结束位置。
3. 二者有两个及两个以上数字的交集,那么不用做任何处理。
好,分析到这里,代码也就不难写出来了,我们用个数组v来表示集合S,初始化放两个-1进去,因为题目中说明了区间都是大于0的,所以我们放这两个数组进去是为了防止越界的,不会有任何影响,最后统计长度的时候减去这个两个数字就可以了。先给区间排序,然后遍历每个区间,如果区间的起始位置小于等于数组的倒数第二个数字,说明此时已经有两个相同的数字了,直接跳过当前区间。否则如果区间的起始位置大于数组的最后一个位置,说明二者没有任何交集,我们此时先把区间的倒数第二小的数字加入数组v中。然后统一再把区间的结束位置加入数组v中,因为不管区间和数组有一个交集还是没有任何交集,结束位置都要加入数组中,所以不用放在if..else..中。最后循环结束,返回数组的大小减2,参见代码如下:
解法一:
class Solution {
public:
int intersectionSizeTwo(vector<vector<int>>& intervals) {
vector<int> v{-, -};
sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b){
return a[] < b[] || (a[] == b[] && a[] > b[]);
});
for (auto &interval : intervals) {
int len = v.size();
if (interval[] <= v[len - ]) continue;
if (interval[] > v.back()) v.push_back(interval[] - );
v.push_back(interval[]);
}
return v.size() - ;
}
};
我们可以对空间复杂度进行优化,我们不用保存整个集合S,因为结果只让我们返回长度即可,所以我们用两个变量p1和p2,其中p1表示集合S中倒数第二大的数字,p2为集合S中最大的数字。我们的整个逻辑跟上面的解法是相同的。遍历区间的时候,如果区间的起始位置小于等于p1,则跳过当前区间。否则如果起始位置大于p2,说明没有交集,需要加上两个数字,结果res自增2,然后p2赋值为当前区间的结束位置,p1赋值为第二大的数字。否则说明只有一个交集,结果res自增1,然后p1赋值为p2,p2赋值为当前区间的结束位置即可,参见代码如下:
解法二:
class Solution {
public:
int intersectionSizeTwo(vector<vector<int>>& intervals) {
int res = , p1 = -, p2 = -;
sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b){
return a[] < b[] || (a[] == b[] && a[] > b[]);
});
for (auto &interval : intervals) {
if (interval[] <= p1) continue;
if (interval[] > p2) {
res += ;
p2 = interval[];
p1 = p2 - ;
} else {
++res;
p1 = p2;
p2 = interval[];
}
}
return res;
}
};
讨论:这道题的一个拓展就是一般化,改为交集大小至少为k,那么我们该怎么做呢?其实也不是很难,我们可以在解法一的基础上进行修改,我们还是用数组v来表示集合S,只不过我们初始化加入k个-1。然后还是要给区间排序,之后进行遍历,如果起始位置小于等于倒数第k个数,跳过当前区间。然后就是重点部分了,我们还是用起始位置跟数组v的最后面的数字比较,总共比到倒数第k-1个数就行了,因为小于等于倒数第k个数已经跳过了。如果大于最后一个数,则将区间后k个数加入数组;否则如果大于倒数第二个数,则将区间后k-1个数加入数组;否则如果大于倒数第三个数,则将数组后k-2个数加入数组,以此类推,直到比完倒数第k-1个数就行了,最后返回的是数组v的长度减去k。
参考资料:
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Set Intersection Size At Least Two 设置交集大小至少为2的更多相关文章
- Java实现 LeetCode 757 设置交集大小至少为2(排序+滑动窗口)
757. 设置交集大小至少为2 一个整数区间 [a, b] ( a < b ) 代表着从 a 到 b 的所有连续整数,包括 a 和 b. 给你一组整数区间intervals,请找到一个最小的集合 ...
- [Swift]LeetCode757. 设置交集大小至少为2 | Set Intersection Size At Least Two
An integer interval [a, b] (for integers a < b) is a set of all consecutive integers from ato b, ...
- [LeetCode] 349. Intersection of Two Arrays 两个数组相交
Given two arrays, write a function to compute their intersection. Example 1: Input: nums1 = [1,2,2,1 ...
- [LeetCode] 350. Intersection of Two Arrays II 两个数组相交II
Given two arrays, write a function to compute their intersection. Example 1: Input: nums1 = [1,2,2,1 ...
- [LeetCode] 160. Intersection of Two Linked Lists 求两个链表的交集
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- [LeetCode] 325. Maximum Size Subarray Sum Equals k 和等于k的最长子数组
Given an array nums and a target value k, find the maximum length of a subarray that sums to k. If t ...
- 【LeetCode题解】349_两个数组的交集
目录 [LeetCode题解]349_两个数组的交集 描述 方法一:两个哈希表 Java 实现 类似的 Java 实现 Python 实现 类似的 Python 实现 方法二:双指针 Java 实现 ...
- 【转】CSS3的REM设置字体大小
rem 长度单位 在Web中使用什么单位来定义页面的字体大小,至今天为止都还在激烈的争论着,有人说PX做为单位好,有人说EM优点多,还有人在说百分比方便,以至于出现了CSS Font-Size: ...
- CSS3的REM设置字体大小
在Web中使用什么单位来定义页面的字体大小,至今天为止都还在激烈的争论着,有人说PX做为单位好,有人说EM优点多,还有人在说百分比方便,以至于出现了CSS Font-Size: em vs. px v ...
随机推荐
- Oracle服务器和客户端的安装和卸载
Oracle 11g服务器与客户端的完全卸载方式与前些版本有了改变: 一.卸载前准备: 开始->设置->控制面板->管理工具->服务 停止所有Oracle服务. 二.批处理卸载 ...
- 使用ADO.NET查询和操作数据
使用ADO.NET查询和操作数据 StringBuilder类: 用来定义可变字符串StringBuilder sb = new StringBuilder("");//追加字符串 ...
- git解决修改代码后无法push的问题failed to push some refs to 'ssh://git@xxx.xxx.xx/xx.git'
今天在使用git提交代码的时候,犯了个很低级的错误,按照一切流程当我add并commit提交代码,最后使用push到远程仓库, 接下来奇怪的事情发生了,push之后,查看远程仓库代码并没有发现提交记录 ...
- Python中的PYTHONPATH环境变量
PYTHONPATH是Python中一个重要的环境变量,用于在导入模块的时候搜索路径.可以通过如下方式访问: >>> import sys >>> sys.path ...
- Vue项目使用CDN优化首屏加载
前言 作为一个网站应用,加载速度是非常重要的.加载速度,一个是程序的合理安排,如以组件按需加载,一个是js.css等资源的异步加载. 在Vue项目中,引入到工程中的所有js.css文件,编译时都会被打 ...
- beta冲刺3
一,昨天的问题: 页面整理还没做 我的社团这边的后台数据库未完成,前端代码修改未完成. 二,今天已完成 页面整理基本完成,把登陆独立出来了,然后基本处理掉了多余页面(反正也没几个--) 我的社团这边试 ...
- 按指定id顺序查询
SELECT a.p,* FROM tb1 t,( as p union as p union as p union as p union as p ) a where t.id=a.id order ...
- 201621123040《Java程序设计》第七周学习总结
1.本周学习总结 1.1思维导图:Java图形界面总结 2.书面作业 2.1GUI中的事件处理 2.1.1写出事件处理模型中最重要的几个关键词. 关键词:事件 事件源 事件监听器 2.1.2任意编写事 ...
- C语言--第0周作业
1.翻阅邹欣老师博客关于师生关系博客,并回答下列问题: 1)最理想的师生关系是健身教练和学员的关系,在这种师生关系中你期望获得来自老师的哪些帮助? 答: 若教练和学员的关系是最理想的师生关系,那就意味 ...
- pop 一个viewController时候会有键盘闪现出来又消失
原因是alertview关闭影响了系统其他的动画导致的.要么延迟调用,要么自己做一个alertview. iOS 8.3,dismiss alert view时系统会尝试恢复之前的keyboard i ...