题目一 聚会分组
题目描述:
n个人要一起参加聚会,其中有些人是互相认识的,问能否将参会的人分成两组并且每组的人互相都不认识。
如4个人, 1认识2, 2认识3, 3认识4 就可以1和3 分一组,2和4分一组,
如果2同时认识3和4,那么就无法进行分组。
题目分析:
将每个人看做一个节点,互相认识的节点用线给连接去起来,这样所有有直接或者间接关系的节点就会组成一个图。
然后使用BFS的方式来便利这个图中的每一个节点,并且在遍历的过程中进行分组,分组的信息可以存储在两个HashSet中。
如果当前节点是组A,那么它所有的连接节点都应该分到组B。
如果发现当前节点的一个连接节点已经分到了和当前节点在同一个组,那么就说明无法按题目要求进行分组了,可以直接返回false。
需要注意的是,上述方式形成的图可能有多个。如多组人,每组中的人都只认识自己组中的人,那么每组人都会形成一个单独的图。
多个图并不会影响上面的解题思路,因为不同图之间是没有影响的,无论图A是如何分组的都不影响图B的分组。
代码:
1 | boolean canDivide(int n, List<List<Integer>> relations) { |
题目二 值班表分组
题目描述:
一天有24个小时,每个人都有一个自己值班的时间段,而且开始结束时间都是整点(不考虑跨过0点的情况),如2点到4点,需要找到所有人值班表所能形成的时间段以及每个时间段里都有谁值班。
如
A: 5点到6点
B: 7点到8点
C: 3点到5点
D: 0点到6点
E: 1点到2点
得出的结果应该是
0点到1点:D
1点到2点:D,E
2点到3点:D,
3点到5点:C,D
5点到6点:A,D
7点到8点:B
题目分析
这道题目需要分两步来解决,第一步确定所有人值班表所能形成的时间段,第二步找出没一个时间段都有谁在值班。
对于第一步,首先要明确怎么才能找出合法的时间段,如果两个时间段 5-6, 7-8, 那么6-7就不是一个合法的时间段,但是如果
多了一个5-8那么6-7因为有人在值班,就变成了一个合法的时间段。那如何确定某个时间段是否有人在值班呢?
每个人的时间段都有开始时间和结束时间,如果将开始时间看做是一个左括号,结束时间看过是一个右括号,那么当一个时间段左括号
的数目大于右括号的时候,这个时间段必然是一个合法的时间段,因为还有右括号就代表着必然还有人的值班时间是覆盖当前时间段的。
所以这个题目就转化为了括号的匹配问题。
这样可以将所有人值班的开始和结束时间放在一起进行排序,同时记录下是否是开始的时间。排好序后遍历所有的时间段并根据上述理论
就可以找出所有合法的时间段。
对于第二步,有了合法的时间段后就可以重复遍历每个人的值班时间,如果值班时间包含了这个时间段,就可以将这个人给添加到这个时间段中。
但是这样的时间复杂度会比较高,每当需要降低一下时间复杂度的时候都要考虑空间换取时间。在这里可以创建一个大小是24的List数组,数组
下标i 代表i 到i+1的时间段。遍历每个人的时间表一次,将人名添加到对应时间点。这样就可以直接将合法时间段所对应的值班人员一下子取出来。
代码:
1 | /** |