Skip to content

Commit 6257eee

Browse files
author
lucifer
committed
feat: $401
1 parent a5b23ab commit 6257eee

File tree

5 files changed

+247
-1
lines changed

5 files changed

+247
-1
lines changed

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
* [0342. 4的幂](problems/342.power-of-four.md)
8080
* [0349. 两个数组的交集](problems/349.intersection-of-two-arrays.md)
8181
* [0371. 两整数之和](problems/371.sum-of-two-integers.md)
82+
* [401. 二进制手表](problems/401.binary-watch.md)
8283
* [0437. 路径总和 III](problems/437.path-sum-iii.md)
8384
* [0455. 分发饼干](problems/455.AssignCookies.md)
8485
* [0575. 分糖果](problems/575.distribute-candies.md)

collections/easy.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
- [0342. 4 的幂](../problems/342.power-of-four.md)
4040
- [0349. 两个数组的交集](../problems/349.intersection-of-two-arrays.md)
4141
- [0371. 两整数之和](../problems/371.sum-of-two-integers.md)
42+
- [401. 二进制手表](../problems/401.binary-watch.md)
4243
- [0437. 路径总和 III](../problems/437.path-sum-iii.md)
4344
- [0455. 分发饼干](../problems/455.AssignCookies.md)
4445
- [0575. 分糖果](../problems/575.distribute-candies.md)

problems/401.binary-watch.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
## 题目地址(401. 二进制手表)
2+
3+
https://leetcode-cn.com/problems/binary-watch/
4+
5+
## 题目描述
6+
7+
```
8+
二进制手表顶部有 4 个 LED 代表 小时(0-11),底部的 6 个 LED 代表 分钟(0-59)。
9+
10+
每个 LED 代表一个 0 或 1,最低位在右侧。
11+
```
12+
![](https://tva1.sinaimg.cn/large/0081Kckwly1gm5szmnbinj31400u0tra.jpg)
13+
14+
```
15+
例如,上面的二进制手表读取 “3:25”。
16+
17+
给定一个非负整数 n 代表当前 LED 亮着的数量,返回所有可能的时间。
18+
19+
 
20+
21+
示例:
22+
23+
输入: n = 1
24+
返回: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]
25+
 
26+
27+
提示:
28+
29+
输出的顺序没有要求。
30+
小时不会以零开头,比如 “01:00” 是不允许的,应为 “1:00”。
31+
分钟必须由两位数组成,可能会以零开头,比如 “10:2” 是无效的,应为 “10:02”。
32+
超过表示范围(小时 0-11,分钟 0-59)的数据将会被舍弃,也就是说不会出现 "13:00", "0:61" 等时间。
33+
34+
来源:力扣(LeetCode)
35+
链接:https://leetcode-cn.com/problems/binary-watch
36+
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
37+
38+
```
39+
40+
## 前置知识
41+
42+
- 笛卡尔积
43+
- [回溯](https://github.com/azl397985856/leetcode/blob/master/thinkings/backtrack.md)
44+
45+
## 公司
46+
47+
- 阿里
48+
- 腾讯
49+
- 百度
50+
- 字节
51+
52+
## 思路
53+
54+
一看题目就是一个笛卡尔积问题。
55+
56+
即给你一个数字 num, 我可以将其分成两部分。其中一部分(不妨设为a)给小时,另一部分给分(就是 num - a)。 最终的结果就是 a 能表示的所有小时的集合和 num - a所能表示的分的集合的笛卡尔积。
57+
58+
用代码表示就是:
59+
60+
```py
61+
# 枚举小时
62+
for a in possible_number(i):
63+
# 小时确定了,分就是 num - i
64+
for b in possible_number(num - i, True):
65+
ans.add(str(a) + ":" + str(b).rjust(2, '0'))
66+
```
67+
68+
枚举所有可能的 (a, num - a) 组合即可。
69+
70+
核心代码:
71+
72+
```py
73+
for i in range(min(4, num + 1)):
74+
for a in possible_number(i):
75+
for b in possible_number(num - i, True):
76+
ans.add(str(a) + ":" + str(b).rjust(2, '0'))
77+
```
78+
79+
## 代码
80+
81+
```py
82+
class Solution:
83+
def readBinaryWatch(self, num: int) -> List[str]:
84+
def possible_number(count, minute=False):
85+
if count == 0: return [0]
86+
if minute:
87+
return filter(lambda a: a < 60, map(sum, combinations([1, 2, 4, 8, 16, 32], count)))
88+
return filter(lambda a: a < 12, map(sum, combinations([1, 2, 4, 8], count)))
89+
ans = set()
90+
for i in range(min(4, num + 1)):
91+
for a in possible_number(i):
92+
for b in possible_number(num - i, True):
93+
ans.add(str(a) + ":" + str(b).rjust(2, '0'))
94+
return list(ans)
95+
```
96+
97+
98+
进一步思考,实际上,我们要找的就是 a 和 b 相加等于 num,并且 a 和 b 就是二进制表示中 1 的个数。 因此可以将逻辑简化为:
99+
100+
101+
```py
102+
class Solution:
103+
def readBinaryWatch(self, num: int) -> List[str]:
104+
return [str(a) + ":" + str(b).rjust(2, '0') for a in range(12) for b in range(60) if (bin(a)+bin(b)).count('1') == num]
105+
```
106+
107+
108+
109+
大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。
110+
大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
111+

thinkings/backtrack.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ class Solution:
166166
参考题目:
167167
168168
- [140. 单词拆分 II](https://github.com/azl397985856/leetcode/blob/master/problems/140.word-break-ii.md)
169+
- [401. 二进制手表](../problems/401.binary-watch.md)
169170
- [816. 模糊坐标](https://github.com/azl397985856/leetcode/blob/master/problems/816.ambiguous-coordinates.md)
170171
171172
这类问题不同于子集和全排列,其组合是有规律的,我们可以使用笛卡尔积公式,将两个或更多子集联合起来。

thinkings/island.md

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,139 @@ class Solution:
133133

134134
如果你下次碰到了小岛题目, 或者可以抽象为小岛类模型的题目,可以尝试使用本节给大家介绍的模板。这种题目的规律性很强, 类似的还有石子游戏,石子游戏大多数可以使用 DP 来做,这就是一种套路。
135135

136-
大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。
136+
137+
## 扩展
138+
139+
实际上,很多题都有小岛题的影子,所谓的小岛题的核心是求连通区域。如果你能将问题转化为求连通区域,那么就可以使用本节的思路去做。 比如 [959. 由斜杠划分区域](https://leetcode-cn.com/problems/regions-cut-by-slashes/ "959. 由斜杠划分区域")
140+
141+
题目描述:
142+
143+
```
144+
在由 1 x 1 方格组成的 N x N 网格 grid 中,每个 1 x 1 方块由 /、\ 或空格构成。这些字符会将方块划分为一些共边的区域。
145+
146+
(请注意,反斜杠字符是转义的,因此 \ 用 "\\" 表示。)。
147+
148+
返回区域的数目。
149+
150+
示例 1:
151+
152+
输入:
153+
[
154+
  " /",
155+
  "/ "
156+
]
157+
输出:2
158+
解释:2x2 网格如下:
159+
```
160+
161+
![](https://tva1.sinaimg.cn/large/0081Kckwly1gm5tfleu8lj302a02aa9y.jpg)
162+
163+
```
164+
165+
示例 2:
166+
167+
输入:
168+
[
169+
  " /",
170+
  " "
171+
]
172+
输出:1
173+
解释:2x2 网格如下:
174+
```
175+
176+
![](https://tva1.sinaimg.cn/large/0081Kckwly1gm5tg0a44lj302b02a3ye.jpg)
177+
178+
```
179+
180+
示例 3:
181+
182+
输入:
183+
[
184+
  "\\/",
185+
  "/\\"
186+
]
187+
输出:4
188+
解释:(回想一下,因为 \ 字符是转义的,所以 "\\/" 表示 \/,而 "/\\" 表示 /\。)
189+
2x2 网格如下:
190+
191+
```
192+
193+
![](https://tva1.sinaimg.cn/large/0081Kckwly1gm5tg5hn8vj302b02at8m.jpg)
194+
195+
```
196+
197+
示例 4:
198+
199+
输入:
200+
[
201+
  "/\\",
202+
  "\\/"
203+
]
204+
输出:5
205+
解释:(回想一下,因为 \ 字符是转义的,所以 "/\\" 表示 /\,而 "\\/" 表示 \/。)
206+
2x2 网格如下:
207+
```
208+
209+
![](https://tva1.sinaimg.cn/large/0081Kckwly1gm5tgi6g9ij3029029jra.jpg)
210+
211+
```
212+
213+
示例 5:
214+
215+
输入:
216+
[
217+
  "//",
218+
  "/ "
219+
]
220+
输出:3
221+
解释:2x2 网格如下:
222+
```
223+
224+
![](https://tva1.sinaimg.cn/large/0081Kckwly1gm5tgn4yysj302a02at8m.jpg)
225+
226+
227+
```
228+
提示:
229+
230+
1 <= grid.length == grid[0].length <= 30
231+
grid[i][j] 是 '/'、'\'、或 ' '。
232+
```
233+
234+
实际上,如果你将题目中的 "/" 和 "\" 都转化为 一个 3 x 3 的网格之后,问题就变成了求连通区域的个数,就可以用本节的思路去解决了。具体留给读者去思考吧,这里给大家贴一个 Python3 的代码。
235+
236+
```py
237+
class Solution:
238+
def regionsBySlashes(self, grid: List[str]) -> int:
239+
m, n = len(grid), len(grid[0])
240+
new_grid = [[0 for _ in range(3 * n)] for _ in range(3 * m)]
241+
ans = 0
242+
# 预处理,生成新的 3 * m * 3 * n 的网格
243+
for i in range(m):
244+
for j in range(n):
245+
if grid[i][j] == '/':
246+
new_grid[3 * i][3 * j + 2] = 1
247+
new_grid[3 * i + 1][3 * j + 1] = 1
248+
new_grid[3 * i + 2][3 * j] = 1
249+
if grid[i][j] == '\\':
250+
new_grid[3 * i][3 * j] = 1
251+
new_grid[3 * i + 1][3 * j + 1] = 1
252+
new_grid[3 * i + 2][3 * j + 2] = 1·
253+
def dfs(i, j):
254+
if 0 <= i < 3 * m and 0 <= j < 3 * n and new_grid[i][j] == 0:
255+
new_grid[i][j] = 1
256+
dfs(i + 1, j)
257+
dfs(i - 1, j)
258+
dfs(i, j + 1)
259+
dfs(i, j - 1)
260+
for i in range(3 * m):
261+
for j in range(3 * n):
262+
if new_grid[i][j] == 0:
263+
ans += 1
264+
dfs(i, j)
265+
return ans
266+
```
267+
268+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。
137269

138270
大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
139271

0 commit comments

Comments
 (0)