Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e42c71d

Browse files
Merge pull request SharingSource#596 from SharingSource/ac_oier
✨feat: add 735、676、1252
2 parents 73a402d + 21eb435 commit e42c71d

File tree

5 files changed

+311
-7
lines changed

5 files changed

+311
-7
lines changed

‎Index/栈.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
| [385. 迷你语法分析器](https://leetcode-cn.com/problems/mini-parser/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/mini-parser/solution/by-ac_oier-zuy6/) | 中等 | 🤩🤩🤩🤩🤩 |
1010
| [591. 标签验证器](https://leetcode-cn.com/problems/tag-validator/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/tag-validator/solution/by-ac_oier-9l8z/) | 困难 | 🤩🤩🤩🤩 |
1111
| [726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/) | 困难 | 🤩🤩🤩🤩 |
12+
| [735. 行星碰撞](https://leetcode.cn/problems/asteroid-collision/) | [LeetCode 题解链接](https://leetcode.cn/problems/asteroid-collision/solution/by-ac_oier-p4qh/) | 中等 | 🤩🤩🤩🤩🤩 |
1213
| [1190. 反转每对括号间的子串](https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/solution/gong-shui-san-xie-shi-yong-shuang-duan-d-r35q/) | 中等 | 🤩🤩🤩🤩🤩 |
1314
| [面试题 03.01. 三合一](https://leetcode-cn.com/problems/three-in-one-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/three-in-one-lcci/solution/yi-ti-shuang-jie-er-wei-shu-zu-yi-wei-sh-lih7/) | 简单 | 🤩🤩🤩 |
1415
| [面试题 02.05. 链表求和](https://leetcode-cn.com/problems/sum-lists-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/sum-lists-lcci/solution/by-ac_oier-v1zb/) | 中等 | 🤩🤩🤩 |

‎Index/模拟.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
| [720. 词典中最长的单词](https://leetcode-cn.com/problems/longest-word-in-dictionary/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/longest-word-in-dictionary/solution/by-ac_oier-bmot/) | 简单 | 🤩🤩🤩🤩 |
8989
| [726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/) | 困难 | 🤩🤩🤩🤩 |
9090
| [729. 我的日程安排表 I](https://leetcode-cn.com/problems/my-calendar-i/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/my-calendar-i/solution/by-ac_oier-1znx/) | 中等 | 🤩🤩🤩 |
91+
| [735. 行星碰撞](https://leetcode.cn/problems/asteroid-collision/) | [LeetCode 题解链接](https://leetcode.cn/problems/asteroid-collision/solution/by-ac_oier-p4qh/) | 中等 | 🤩🤩🤩🤩🤩 |
9192
| [747. 至少是其他数字两倍的最大数](https://leetcode-cn.com/problems/largest-number-at-least-twice-of-others/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/largest-number-at-least-twice-of-others/solution/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-8179/) | 简单 | 🤩🤩🤩🤩🤩 |
9293
| [748. 最短补全词](https://leetcode-cn.com/problems/shortest-completing-word/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/shortest-completing-word/solution/gong-shui-san-xie-jian-dan-zi-fu-chuan-j-x4ao/) | 简单 | 🤩🤩🤩🤩 |
9394
| [762. 二进制表示中质数个计算置位](https://leetcode-cn.com/problems/prime-number-of-set-bits-in-binary-representation/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/prime-number-of-set-bits-in-binary-representation/solution/by-ac_oier-w50x/) | 简单 | 🤩🤩🤩🤩 |

‎LeetCode/1251-1260/1252. 奇数值单元格的数目(简单).md‎

Lines changed: 97 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Tag : 「模拟」、「位运算」、「计数」
6464

6565
当 $r[idx]$ 为 `True` 含义为第 $idx$ 行的累加值为奇数,否则为偶数。列数组 `c` 的统计规则同理。
6666

67-
代码:
67+
Java 代码:
6868
```Java
6969
class Solution {
7070
public int oddCells(int m, int n, int[][] ins) {
@@ -78,6 +78,29 @@ class Solution {
7878
}
7979
}
8080
```
81+
TypeScript 代码:
82+
```TypeScript
83+
function oddCells(m: number, n: number, ins: number[][]): number {
84+
const r = new Array<boolean>(m).fill(false), c = new Array<boolean>(n).fill(false)
85+
let a = 0, b = 0
86+
for (const [i, j] of ins) {
87+
a += (r[i] = !r[i]) ? 1 : -1
88+
b += (c[j] = !c[j]) ? 1 : -1
89+
}
90+
return a * (n - b) + (m - a) * b
91+
};
92+
```
93+
Python 代码:
94+
```Python3
95+
class Solution:
96+
def oddCells(self, m: int, n: int, ins: List[List[int]]) -> int:
97+
r, c = [False] * m, [False] * n
98+
for i, j in ins:
99+
r[i] ^= 1
100+
c[j] ^= 1
101+
a, b = sum(r), sum(c)
102+
return a * (n - b) + (m - a) * b
103+
```
81104
* 时间复杂度:构建计数数组的复杂度为 $O(m + n),ドル统计奇数行和奇数列复杂度为 $O(l),ドル其中 $l$ 为数组 `ins` 的长度,复杂度为 $O(m + n + l)$
82105
* 空间复杂度:$O(m + n)$
83106

@@ -87,9 +110,9 @@ class Solution {
87110

88111
更进一步,我们可以使用两个 `long` 变量 $c1$ 和 $c2$ 来分别充当行和列的计数数组,当 $c1$ 的第 $k$ 位为 1ドル,ドル代表第 $k$ 行累加值为奇数,当 $c1$ 的第 $k$ 位为 0ドル,ドル代表第 $k$ 行累加值为偶数;$c2$ 的计数规则同理。而翻转二进制中的某一位可使用「异或」操作。
89112

90-
当处理完所有的 `ins` 之后,可通过「遍历 $c1$ 的低 $m$ 位 + 遍历 $c2$ 的低 $n$ 位」来得到行数中奇数个数 $a,ドル列数中奇数个数 $b,ドル复杂度为 $O(m + n)$;也使用 `bitCount` 统计 `long` 二进制数中 1ドル$ 的个数(本质是分治操作),复杂度为 $O(\log{64})$。
113+
当处理完所有的 `ins` 之后,可通过「遍历 $c1$ 的低 $m$ 位 + 遍历 $c2$ 的低 $n$ 位」来得到行数中奇数个数 $a,ドル列数中奇数个数 $b,ドル复杂度为 $O(m + n)$;也可以使用 `bitCount` 统计 `long` 二进制数中 1ドル$ 的个数(本质是分治操作),复杂度为 $O(\log{64})$。
91114

92-
代码:
115+
Java 代码:
93116
```Java
94117
class Solution {
95118
public int oddCells(int m, int n, int[][] ins) {
@@ -105,9 +128,7 @@ class Solution {
105128
}
106129
}
107130
```
108-
109-
-
110-
131+
Java 代码:
111132
```Java
112133
class Solution {
113134
public int oddCells(int m, int n, int[][] ins) {
@@ -121,11 +142,81 @@ class Solution {
121142
}
122143
}
123144
```
145+
TypeScript 代码:
146+
```TypeScript
147+
function oddCells(m: number, n: number, ins: number[][]): number {
148+
const c1 = [0, 0], c2 = [0, 0]
149+
for (const [i, j] of ins) {
150+
c1[Math.ceil(i / 32)] ^= (1 << (i % 32))
151+
c2[Math.ceil(j / 32)] ^= (1 << (j % 32))
152+
}
153+
let a = 0, b = 0
154+
for (let i = 0; i < m; i++) a += (c1[Math.ceil(i / 32)] >> (i % 32) & 1)
155+
for (let i = 0; i < n; i++) b += (c2[Math.ceil(i / 32)] >> (i % 32) & 1)
156+
return a * (n - b) + (m - a) * b
157+
};
158+
```
159+
Python 代码:
160+
```Python3
161+
class Solution:
162+
def oddCells(self, m: int, n: int, ins: List[List[int]]) -> int:
163+
c1, c2 = 0, 0
164+
for i, j in ins:
165+
c1 ^= (1 << i)
166+
c2 ^= (1 << j)
167+
a, b = 0, 0
168+
for i in range(m):
169+
a += (c1 >> i) & 1
170+
for i in range(n):
171+
b += (c2 >> i) & 1
172+
return a * (n - b) + (m - a) * b
173+
```
124174
* 时间复杂度:处理所有的 `ins` 复杂度为 $O(l),ドル其中 $l$ 为数组 `ins` 的长度;使用遍历方式统计奇数行和奇数列个数复杂度为 $O(m + n)$;使用 `bitCount` 操作统计二进制中 1ドル$ 个数,复杂度为 $O(\log{C}),ドル其中 $C = 64$ 为 `long` 二进制数长度,整体复杂度为 $O(l + m + n)$ 或 $O(l + \log{C})$
125175
* 空间复杂度:$O(1)$
126176

127177
---
128178

179+
### 答疑
180+
181+
评论区有同学提到 `bitCount` 的复杂度问题,如下是 `Long.bitCount` 操作的源码:
182+
183+
```Java
184+
public static int bitCount(long i) {
185+
// HD, Figure 5-14
186+
i = i - ((i >>> 1) & 0x5555555555555555L);
187+
i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L);
188+
i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
189+
i = i + (i >>> 8);
190+
i = i + (i >>> 16);
191+
i = i + (i >>> 32);
192+
return (int)i & 0x7f;
193+
}
194+
```
195+
196+
这自然不是通过遍历统计位数的 $O(n)$ 做法,普遍会认为是 $O(1)$。
197+
198+
但上述操作目的是进行成组统计(分治),而能够这样写是因为默认了 `long` 是 64ドル$ 长度,因此严格意义来说这段代码复杂度是 $O(\log{64})$ 的。
199+
200+
作为对比,可以把 `Integer.bitCount` 的源码看一下:
201+
202+
```Java
203+
public static int bitCount(int i) {
204+
// HD, Figure 5-2
205+
i = i - ((i >>> 1) & 0x55555555);
206+
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
207+
i = (i + (i >>> 4)) & 0x0f0f0f0f;
208+
i = i + (i >>> 8);
209+
i = i + (i >>> 16);
210+
return i & 0x3f;
211+
}
212+
```
213+
214+
统计原理如出一辙,而能够这样统计,是因为默认了 `int` 长度为 32ドル,ドル其分组统计所需要的操作次数也与二进制数的长度相关,因此复杂度为 $O(\log{32})$。
215+
216+
将上述两个 `bitCount` 视为 $O(1)$ 都是不对的。
217+
218+
---
219+
129220
### 最后
130221

131222
这是我们「刷穿 LeetCode」系列文章的第 `No.1252` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

‎LeetCode/671-680/676. 实现一个魔法字典(中等).md‎

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ magicDictionary.search("leetcoded"); // 返回 False
5959

6060
> **不了解「Trie / 字典树」的同学可以看前置 🧀:[字典树入门](https://mp.weixin.qq.com/s?__biz=MzU4NDE3MTEyMA==&mid=2247488490&idx=1&sn=db2998cb0e5f08684ee1b6009b974089)。里面通过图例展示了字典树基本形态,以及提供了「数组实现」和「TrieNode 实现」两种方式,还有「数组大小估算方式」和「Trie 应用面」介绍**
6161
62-
代码:
62+
Java 代码:
6363
```Java
6464
class MagicDictionary {
6565
int N = 100 * 100, M = 26, idx = 0;
@@ -92,11 +92,100 @@ class MagicDictionary {
9292
}
9393
}
9494
```
95+
TypeScript 代码:
96+
```TypeScript
97+
class MagicDictionary {
98+
N: number = 100 * 100; M: number = 26; idx: number = 0;
99+
tr: number[][] = new Array<Array<number>>(this.N)
100+
isEnd: boolean[] = new Array<boolean>(this.N * this.M).fill(false)
101+
add(s: string): void {
102+
let p = 0
103+
for (let i = 0; i < s.length; i++) {
104+
const u = s.charCodeAt(i) - 'a'.charCodeAt(0)
105+
if (this.tr[p] == undefined) this.tr[p] = new Array<number>(this.M).fill(0)
106+
if (this.tr[p][u] == 0) this.tr[p][u] = ++this.idx
107+
p = this.tr[p][u]
108+
}
109+
this.isEnd[p] = true
110+
}
111+
query(s: string, idx: number, p: number, limit: number): boolean {
112+
if (limit < 0) return false
113+
if (idx == s.length) return this.isEnd[p] && limit == 0
114+
const u = s.charCodeAt(idx) - 'a'.charCodeAt(0)
115+
for (let i = 0; i < 26; i++) {
116+
if (this.tr[p] == undefined || this.tr[p][i] == 0) continue
117+
if (this.query(s, idx + 1, this.tr[p][i], i == u ? limit : limit - 1)) return true
118+
}
119+
return false
120+
}
121+
buildDict(ss: string[]): void {
122+
for (const s of ss) this.add(s)
123+
}
124+
search(s: string): boolean {
125+
return this.query(s, 0, 0, 1)
126+
}
127+
}
128+
```
95129
* 时间复杂度:`buildDict` 操作需要将所有字符存入 `Trie`,复杂度为 $\sum_{i = 0}^{n - 1} len(ss[i]])$;`search` 操作在不考虑 `limit` 以及字典树中最多只有 100ドル$ 具体方案所带来的剪枝效果的话,最坏情况下要搜索所有 $C^L$ 个方案,其中 $C = 26$ 为字符集大小,$L = 100$ 为搜索字符串的最大长度
96130
* 空间复杂度:$O(N \times L \times C),ドル其中 $N = 100$ 为存入 `Trie` 的最大方案数,$L = 100$ 为存入字符串的最大长度,$C = 26$ 为字符集大小
97131

98132
---
99133

134+
### 模拟
135+
136+
当然,利用数据范围只有 100ドル,ドル直接使用模拟也是可以的。
137+
138+
Java 代码:
139+
```Java
140+
class MagicDictionary {
141+
String[] ss;
142+
public void buildDict(String[] _ss) {
143+
ss = _ss;
144+
}
145+
public boolean search(String str) {
146+
for (String s : ss) {
147+
int cnt = 0;
148+
for (int i = 0; s.length() == str.length() && i < s.length() && cnt <= 1; i++) {
149+
if (s.charAt(i) != str.charAt(i)) cnt++;
150+
}
151+
if (cnt == 1) return true;
152+
}
153+
return false;
154+
}
155+
}
156+
```
157+
TypeScript 代码:
158+
```TypeScript
159+
class MagicDictionary {
160+
ss: string[]
161+
buildDict(_ss: string[]): void {
162+
this.ss = _ss
163+
}
164+
search(s: string): boolean {
165+
for (const str of this.ss) {
166+
let cnt = 0
167+
for (let i = 0; str.length == s.length && i < s.length && cnt <= 1; i++) {
168+
if (s.charAt(i) != str.charAt(i)) cnt++
169+
}
170+
if (cnt == 1) return true
171+
}
172+
return false
173+
}
174+
}
175+
```
176+
* 时间复杂度:`buildDict` 操作复杂度为 $O(1)$;`search` 操作复杂度为 $O(n \times L),ドル其中 $n$ 为数组 `ss` 的长度,$L$ 为查询字符串的长度
177+
* 空间复杂度:$O(n)$
178+
179+
---
180+
181+
### 加餐
182+
183+
1. 前置练习题 [可用 Trie 进阶的模拟题](https://mp.weixin.qq.com/s?__biz=MzU4NDE3MTEyMA==&mid=2247492214&idx=1&sn=40fa070fe3b014873297f7ff740ba60f)
184+
185+
2. 另外一道 [结合 DFS 的 Trie 运用题](https://mp.weixin.qq.com/s?__biz=MzU4NDE3MTEyMA==&mid=2247492188&idx=1&sn=a1436d1ffe2b8200a36c3196ca1c7ed1)
186+
187+
---
188+
100189
### 最后
101190

102191
这是我们「刷穿 LeetCode」系列文章的第 `No.676` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[735. 行星碰撞](https://leetcode.cn/problems/asteroid-collision/solution/by-ac_oier-p4qh/)** ,难度为 **中等**
4+
5+
Tag : 「栈」、「模拟」
6+
7+
8+
9+
给定一个整数数组 `asteroids`,表示在同一行的行星。
10+
11+
对于数组中的每一个元素,其绝对值表示行星的大小,正负表示行星的移动方向(正表示向右移动,负表示向左移动)。每一颗行星以相同的速度移动。
12+
13+
找出碰撞后剩下的所有行星。碰撞规则:两个行星相互碰撞,较小的行星会爆炸。如果两颗行星大小相同,则两颗行星都会爆炸。两颗移动方向相同的行星,永远不会发生碰撞。
14+
15+
示例 1:
16+
```
17+
输入:asteroids = [5,10,-5]
18+
19+
输出:[5,10]
20+
21+
解释:10 和 -5 碰撞后只剩下 10 。 5 和 10 永远不会发生碰撞。
22+
```
23+
示例 2:
24+
```
25+
输入:asteroids = [8,-8]
26+
27+
输出:[]
28+
29+
解释:8 和 -8 碰撞后,两者都发生爆炸。
30+
```
31+
示例 3:
32+
```
33+
输入:asteroids = [10,2,-5]
34+
35+
输出:[10]
36+
37+
解释:2 和 -5 发生碰撞后剩下 -5 。10 和 -5 发生碰撞后剩下 10 。
38+
```
39+
40+
提示:
41+
* 2ドル <= asteroids.length <= 10^4$
42+
* $-1000 <= asteroids[i] <= 1000$
43+
* $asteroids[i] != 0$
44+
45+
---
46+
47+
### 模拟 + 栈
48+
49+
为了方便,我们令 `asteroids``ats`
50+
51+
由于碰撞抵消总是从相邻行星之间发生,我们可以使用「栈」来模拟该过程。
52+
53+
从前往后处理所有的 $ats[i],ドル使用栈存储当前未被抵消的行星,当栈顶元素方向往右,当前 $ats[i]$ 方向往左时,会发生抵消操作,抵消过程根据规则进行即可。
54+
55+
Java 代码:
56+
```Java
57+
class Solution {
58+
public int[] asteroidCollision(int[] ats) {
59+
Deque<Integer> d = new ArrayDeque<>();
60+
for (int t : ats) {
61+
boolean ok = true;
62+
while (ok && !d.isEmpty() && d.peekLast() > 0 && t < 0) {
63+
int a = d.peekLast(), b = -t;
64+
if (a <= b) d.pollLast();
65+
if (a >= b) ok = false;
66+
}
67+
if (ok) d.addLast(t);
68+
}
69+
int sz = d.size();
70+
int[] ans = new int[sz];
71+
while (!d.isEmpty()) ans[--sz] = d.pollLast();
72+
return ans;
73+
}
74+
}
75+
```
76+
TypeScript 代码:
77+
```TypeScript
78+
function asteroidCollision(ats: number[]): number[] {
79+
const stk: number[] = new Array<number>()
80+
for (const t of ats) {
81+
let ok: boolean = true
82+
while (ok && stk.length > 0 && stk[stk.length - 1] > 0 && t < 0) {
83+
const a = stk[stk.length - 1], b = -t
84+
if (a <= b) stk.pop()
85+
if (a >= b) ok = false
86+
}
87+
if (ok) stk.push(t)
88+
}
89+
return stk
90+
};
91+
```
92+
Python 3 代码:
93+
```Python3
94+
class Solution:
95+
def asteroidCollision(self, ats: List[int]) -> List[int]:
96+
stk = []
97+
for t in ats:
98+
ok = True
99+
while ok and stk and stk[-1] > 0 and t < 0:
100+
a, b = stk[-1], -t
101+
if a <= b:
102+
stk.pop(-1)
103+
if a >= b:
104+
ok = False
105+
if ok:
106+
stk.append(t)
107+
return stk
108+
```
109+
* 时间复杂度:$O(n)$
110+
* 空间复杂度:$O(n)$
111+
112+
---
113+
114+
### 最后
115+
116+
这是我们「刷穿 LeetCode」系列文章的第 `No.735` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
117+
118+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
119+
120+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
121+
122+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /