A cinema has n
rows of seats, numbered from 1 to n
and there are ten seats in each row, labelled from 1 to 10 as shown in the figure above.
Given the array reservedSeats
containing the numbers of seats already reserved, for example, reservedSeats[i] = [3,8]
means the seat located in row 3 and labelled with 8 is already reserved.
Return the maximum number of four-person groups you can assign on the cinema seats. A four-person group occupies four adjacent seats in one single row. Seats across an aisle (such as [3,3] and [3,4]) are not considered to be adjacent, but there is an exceptional case on which an aisle split a four-person group, in that case, the aisle split a four-person group in the middle, which means to have two people on each side.
Example 1:
Input: n = 3, reservedSeats = [[1,2],[1,3],[1,8],[2,6],[3,1],[3,10]] Output: 4 Explanation: The figure above shows the optimal allocation for four groups, where seats mark with blue are already reserved and contiguous seats mark with orange are for one group.
Example 2:
Input: n = 2, reservedSeats = [[2,1],[1,8],[2,6]] Output: 2
Example 3:
Input: n = 4, reservedSeats = [[4,3],[1,4],[4,6],[1,7]] Output: 4
Constraints:
1 <= n <= 10^9
1 <= reservedSeats.length <= min(10*n, 10^4)
reservedSeats[i].length == 2
1 <= reservedSeats[i][0] <= n
1 <= reservedSeats[i][1] <= 10
- All
reservedSeats[i]
are distinct.
安排电影院座位。
如上图所示,电影院的观影厅中有 n 行座位,行编号从 1 到 n ,且每一行内总共有 10 个座位,列编号从 1 到 10 。
给你数组 reservedSeats ,包含所有已经被预约了的座位。比如说,researvedSeats[i]=[3,8] ,它表示第 3 行第 8 个座位被预约了。
请你返回 最多能安排多少个 4 人家庭 。4 人家庭要占据 同一行内连续 的 4 个座位。隔着过道的座位(比方说 [3,3] 和 [3,4])不是连续的座位,但是如果你可以将 4 人家庭拆成过道两边各坐 2 人,这样子是允许的。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cinema-seat-allocation
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路是贪心 + 位运算。这里贪心的原则是对于每一行row,我们优先查看是否能满足两个家庭,如果实在不满足,我们再看是否能满足一个家庭。具体的做法是,我们创建一个hashmap<Integer, Integer>,key代表当前扫描的行row,value代表这一行已经被reserve的座位。当在同一行中有多行被reserve的时候,我们通过把1左移col个位置来记录,比如当前行的第一个位子和第二个位子被reserve了,我们就把1左移一位的结果和把1左移两位的结果做OR操作。
之后我们再次遍历hashmap的keyset(),这里遍历的思路是对于每一行row,我们来查看到底能满足多少个家庭。根据条件,虽然座位号是从1到10,但是位置1和10是否坐人是没有影响的,如果要满足两个四人家庭,那么座位2345要连续空着,6789要连续空着。如果上述条件不满足,也许能满足一个家庭,那么4567要连续空着。检查这几个位置是否连续空着。因为一开始记录已经被占的位置是通过把1左移若干位得到的,所以如果某个位置被reserve,这一位扇应该是1。所以当我们去检查比如2345这几个位置是否空着的时候,我们可以把map.get(row)背后的value直接和60,960,240做AND操作,如果结果为0则说明这几个位置是空着的。
举个例子,以下的二进制表示座位号1到10的时候是从右往左看的,但是因为表示二进制的时候第一位只能从0开始,所以我们计算座位号的时候,实际是从0到9计算的。如果reserve记录的结果和如下的数字(对应digit上都是1)做AND == 0的话,说明相同位置上的digit都是0,因为0 & 1 == 0。
60的二进制表示是 0000111100 - 2345这几个位子是空的
960的二进制表示是 1111000000 - 6789这几个位子是空的
240的二进制表示是 0011110000 - 4567这几个位子是空的
最后注意return的东西,max自然是过程中我们计算的能为四人家庭reserve的座位数量,同时还需要再加上某些row没有任何预约的情形。
时间O(n)
空间O(n)
Java实现
1 class Solution { 2 public int maxNumberOfFamilies(int n, int[][] reservedSeats) { 3 HashMap<Integer, Integer> map = new HashMap<>(); 4 for (int[] seat : reservedSeats) { 5 int row = seat[0]; 6 int col = seat[1]; 7 // create a bit vector of reserved seats 8 map.put(row, map.getOrDefault(row, 0) | (1 << col)); 9 } 10 int max = 0; 11 for (int row : map.keySet()) { 12 int reserved = map.get(row); 13 int cnt = 0; 14 if ((reserved & 60) == 0) { 15 cnt += 1; // check if seats 2,3,4,5 are available 16 } 17 if ((reserved & 960) == 0) { 18 cnt += 1; // check if seats 6,7,8,9 are available 19 } 20 if ((reserved & 240) == 0 && cnt == 0) { 21 cnt = 1; // check if seats 4,5,6,7 are available 22 } 23 max += cnt; 24 } 25 // map.size()是已经有预约的rows 26 // n - map.size()是没有任何预约的rows 27 return max + 2 * (n - map.size()); 28 } 29 }