diff --git a/README_EN.md b/README_EN.md index 5d2788b28fd19..c765249d724b4 100644 --- a/README_EN.md +++ b/README_EN.md @@ -14,7 +14,9 @@ ## Introduction -Complete solutions to LeetCode, LCOF and LCCI problems, updated daily. Please give me a [star](https://github.com/doocs/leetcode) 🌟 if you like it. +The Doocs LeetCode repository is a comprehensive collection of solutions to LeetCode questions in multiple programming languages. The repository contains solutions to LeetCode, LCOF, LCCI questions, and more in multiple programming languages. + +The repository is maintained by the Doocs community, and please give us a [star](https://github.com/doocs/leetcode) 🌟 if you like it. [中文文档](/README.md) diff --git a/solution/0000-0099/0014.Longest Common Prefix/README.md b/solution/0000-0099/0014.Longest Common Prefix/README.md index 256b7424eff09..8833d09efc682 100644 --- a/solution/0000-0099/0014.Longest Common Prefix/README.md +++ b/solution/0000-0099/0014.Longest Common Prefix/README.md @@ -229,6 +229,27 @@ impl Solution { } ``` +### **PHP** + +```php +class Solution { + /** + * @param String[] $strs + * @return String + */ + function longestCommonPrefix($strs) { + $rs = ""; + for ($i = 0; $i < strlen($strs[0]); $i++) { + for ($j = 1; $j < count($strs); $j++) { + if ($strs[0][$i] != $strs[$j][$i]) return $rs; + } + $rs = $rs.$strs[0][$i]; + } + return $rs; + } +} +``` + ### **...** ``` diff --git a/solution/0000-0099/0014.Longest Common Prefix/README_EN.md b/solution/0000-0099/0014.Longest Common Prefix/README_EN.md index 7664694e817e6..b7ab273bc6e2c 100644 --- a/solution/0000-0099/0014.Longest Common Prefix/README_EN.md +++ b/solution/0000-0099/0014.Longest Common Prefix/README_EN.md @@ -220,6 +220,27 @@ impl Solution { } ``` +### **PHP** + +```php +class Solution { + /** + * @param String[] $strs + * @return String + */ + function longestCommonPrefix($strs) { + $rs = ""; + for ($i = 0; $i < strlen($strs[0]); $i++) { + for ($j = 1; $j < count($strs); $j++) { + if ($strs[0][$i] != $strs[$j][$i]) return $rs; + } + $rs = $rs.$strs[0][$i]; + } + return $rs; + } +} +``` + ### **...** ``` diff --git a/solution/0000-0099/0014.Longest Common Prefix/Solution.php b/solution/0000-0099/0014.Longest Common Prefix/Solution.php new file mode 100644 index 0000000000000..3f472b6b5f1de --- /dev/null +++ b/solution/0000-0099/0014.Longest Common Prefix/Solution.php @@ -0,0 +1,16 @@ +class Solution { + /** + * @param String[] $strs + * @return String + */ + function longestCommonPrefix($strs) { + $rs = ""; + for ($i = 0; $i < strlen($strs[0]); $i++) { + for ($j = 1; $j < count($strs); $j++) { + if ($strs[0][$i] != $strs[$j][$i]) return $rs; + } + $rs = $rs.$strs[0][$i]; + } + return $rs; + } +} \ No newline at end of file diff --git a/solution/0200-0299/0207.Course Schedule/README.md b/solution/0200-0299/0207.Course Schedule/README.md index b6d89840e9b58..8f30283ba7787 100644 --- a/solution/0200-0299/0207.Course Schedule/README.md +++ b/solution/0200-0299/0207.Course Schedule/README.md @@ -50,7 +50,13 @@ **方法一:拓扑排序** -BFS 实现。 +对于本题,我们可以将课程看作图中的节点,先修课程看作图中的边,那么我们可以将本题转化为判断有向图中是否存在环。 + +具体地,我们可以使用拓扑排序的思想,对于每个入度为 $0$ 的节点,我们将其出度的节点的入度减 $1$,直到所有节点都被遍历到。 + +如果所有节点都被遍历到,说明图中不存在环,那么我们就可以完成所有课程的学习;否则,我们就无法完成所有课程的学习。 + +时间复杂度 $O(n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别为课程数和先修课程数。 @@ -67,7 +73,7 @@ class Solution: g[b].append(a) indeg[a] += 1 cnt = 0 - q = deque([i for i, v in enumerate(indeg) if v == 0]) + q = deque(i for i, x in enumerate(indeg) if x == 0) while q: i = q.popleft() cnt += 1 @@ -114,36 +120,6 @@ class Solution { } ``` -### **TypeScrpt** - -```ts -function canFinish(numCourses: number, prerequisites: number[][]): boolean { - let g = Array.from({ length: numCourses }, () => []); - let indeg = new Array(numCourses).fill(0); - for (let [a, b] of prerequisites) { - g[b].push(a); - ++indeg[a]; - } - let q = []; - for (let i = 0; i < numCourses; ++i) { - if (!indeg[i]) { - q.push(i); - } - } - let cnt = 0; - while (q.length) { - const i = q.shift(); - ++cnt; - for (let j of g[i]) { - if (--indeg[j] == 0) { - q.push(j); - } - } - } - return cnt == numCourses; -} -``` - ### **C++** ```cpp @@ -158,15 +134,21 @@ public: ++indeg[a]; } queue q; - for (int i = 0; i < numCourses; ++i) - if (indeg[i] == 0) q.push(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } int cnt = 0; while (!q.empty()) { int i = q.front(); q.pop(); ++cnt; - for (int j : g[i]) - if (--indeg[j] == 0) q.push(j); + for (int j : g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } } return cnt == numCourses; } @@ -185,8 +167,8 @@ func canFinish(numCourses int, prerequisites [][]int) bool { indeg[a]++ } q := []int{} - for i, v := range indeg { - if v == 0 { + for i, x := range indeg { + if x == 0 { q = append(q, i) } } @@ -206,36 +188,65 @@ func canFinish(numCourses int, prerequisites [][]int) bool { } ``` +### **TypeScript** + +```ts +function canFinish(numCourses: number, prerequisites: number[][]): boolean { + const g: number[][] = new Array(numCourses).fill(0).map(() => []); + const indeg: number[] = new Array(numCourses).fill(0); + for (const [a, b] of prerequisites) { + g[b].push(a); + indeg[a]++; + } + const q: number[] = []; + for (let i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } + let cnt = 0; + while (q.length) { + const i = q.shift()!; + cnt++; + for (const j of g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } + } + return cnt == numCourses; +} +``` + ### **C#** ```cs public class Solution { public bool CanFinish(int numCourses, int[][] prerequisites) { var g = new List[numCourses]; - for (int i = 0; i < numCourses; ++i) - { + for (int i = 0; i < numCourses; ++i) { g[i] = new List(); } var indeg = new int[numCourses]; - foreach (var p in prerequisites) - { + foreach (var p in prerequisites) { int a = p[0], b = p[1]; g[b].Add(a); ++indeg[a]; } var q = new Queue(); - for (int i = 0; i < numCourses; ++i) - { - if (indeg[i] == 0) q.Enqueue(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.Enqueue(i); + } } var cnt = 0; - while (q.Count > 0) - { + while (q.Count > 0) { int i = q.Dequeue(); ++cnt; - foreach (int j in g[i]) - { - if (--indeg[j] == 0) q.Enqueue(j); + foreach (int j in g[i]) { + if (--indeg[j] == 0) { + q.Enqueue(j); + } } } return cnt == numCourses; diff --git a/solution/0200-0299/0207.Course Schedule/README_EN.md b/solution/0200-0299/0207.Course Schedule/README_EN.md index 39e7fe1f50f23..afa683330d236 100644 --- a/solution/0200-0299/0207.Course Schedule/README_EN.md +++ b/solution/0200-0299/0207.Course Schedule/README_EN.md @@ -57,7 +57,7 @@ class Solution: g[b].append(a) indeg[a] += 1 cnt = 0 - q = deque([i for i, v in enumerate(indeg) if v == 0]) + q = deque(i for i, x in enumerate(indeg) if x == 0) while q: i = q.popleft() cnt += 1 @@ -102,36 +102,6 @@ class Solution { } ``` -### **TypeScript** - -```ts -function canFinish(numCourses: number, prerequisites: number[][]): boolean { - let g = Array.from({ length: numCourses }, () => []); - let indeg = new Array(numCourses).fill(0); - for (let [a, b] of prerequisites) { - g[b].push(a); - ++indeg[a]; - } - let q = []; - for (let i = 0; i < numCourses; ++i) { - if (!indeg[i]) { - q.push(i); - } - } - let cnt = 0; - while (q.length) { - const i = q.shift(); - ++cnt; - for (let j of g[i]) { - if (--indeg[j] == 0) { - q.push(j); - } - } - } - return cnt == numCourses; -} -``` - ### **C++** ```cpp @@ -146,15 +116,21 @@ public: ++indeg[a]; } queue q; - for (int i = 0; i < numCourses; ++i) - if (indeg[i] == 0) q.push(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } int cnt = 0; while (!q.empty()) { int i = q.front(); q.pop(); ++cnt; - for (int j : g[i]) - if (--indeg[j] == 0) q.push(j); + for (int j : g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } } return cnt == numCourses; } @@ -173,8 +149,8 @@ func canFinish(numCourses int, prerequisites [][]int) bool { indeg[a]++ } q := []int{} - for i, v := range indeg { - if v == 0 { + for i, x := range indeg { + if x == 0 { q = append(q, i) } } @@ -194,36 +170,65 @@ func canFinish(numCourses int, prerequisites [][]int) bool { } ``` +### **TypeScript** + +```ts +function canFinish(numCourses: number, prerequisites: number[][]): boolean { + const g: number[][] = new Array(numCourses).fill(0).map(() => []); + const indeg: number[] = new Array(numCourses).fill(0); + for (const [a, b] of prerequisites) { + g[b].push(a); + indeg[a]++; + } + const q: number[] = []; + for (let i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } + let cnt = 0; + while (q.length) { + const i = q.shift()!; + cnt++; + for (const j of g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } + } + return cnt == numCourses; +} +``` + ### **C#** ```cs public class Solution { public bool CanFinish(int numCourses, int[][] prerequisites) { var g = new List[numCourses]; - for (int i = 0; i < numCourses; ++i) - { + for (int i = 0; i < numCourses; ++i) { g[i] = new List(); } var indeg = new int[numCourses]; - foreach (var p in prerequisites) - { + foreach (var p in prerequisites) { int a = p[0], b = p[1]; g[b].Add(a); ++indeg[a]; } var q = new Queue(); - for (int i = 0; i < numCourses; ++i) - { - if (indeg[i] == 0) q.Enqueue(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.Enqueue(i); + } } var cnt = 0; - while (q.Count > 0) - { + while (q.Count > 0) { int i = q.Dequeue(); ++cnt; - foreach (int j in g[i]) - { - if (--indeg[j] == 0) q.Enqueue(j); + foreach (int j in g[i]) { + if (--indeg[j] == 0) { + q.Enqueue(j); + } } } return cnt == numCourses; diff --git a/solution/0200-0299/0207.Course Schedule/Solution.cpp b/solution/0200-0299/0207.Course Schedule/Solution.cpp index b4d2e1e28f0d4..9251c69502002 100644 --- a/solution/0200-0299/0207.Course Schedule/Solution.cpp +++ b/solution/0200-0299/0207.Course Schedule/Solution.cpp @@ -9,15 +9,21 @@ class Solution { ++indeg[a]; } queue q; - for (int i = 0; i < numCourses; ++i) - if (indeg[i] == 0) q.push(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } int cnt = 0; while (!q.empty()) { int i = q.front(); q.pop(); ++cnt; - for (int j : g[i]) - if (--indeg[j] == 0) q.push(j); + for (int j : g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } } return cnt == numCourses; } diff --git a/solution/0200-0299/0207.Course Schedule/Solution.cs b/solution/0200-0299/0207.Course Schedule/Solution.cs index 97ccfb4067ba0..5d11635a0455e 100644 --- a/solution/0200-0299/0207.Course Schedule/Solution.cs +++ b/solution/0200-0299/0207.Course Schedule/Solution.cs @@ -1,30 +1,29 @@ public class Solution { public bool CanFinish(int numCourses, int[][] prerequisites) { var g = new List[numCourses]; - for (int i = 0; i < numCourses; ++i) - { + for (int i = 0; i < numCourses; ++i) { g[i] = new List(); } var indeg = new int[numCourses]; - foreach (var p in prerequisites) - { + foreach (var p in prerequisites) { int a = p[0], b = p[1]; g[b].Add(a); ++indeg[a]; } var q = new Queue(); - for (int i = 0; i < numCourses; ++i) - { - if (indeg[i] == 0) q.Enqueue(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.Enqueue(i); + } } var cnt = 0; - while (q.Count > 0) - { + while (q.Count > 0) { int i = q.Dequeue(); ++cnt; - foreach (int j in g[i]) - { - if (--indeg[j] == 0) q.Enqueue(j); + foreach (int j in g[i]) { + if (--indeg[j] == 0) { + q.Enqueue(j); + } } } return cnt == numCourses; diff --git a/solution/0200-0299/0207.Course Schedule/Solution.go b/solution/0200-0299/0207.Course Schedule/Solution.go index 87a4a3e428023..f76b3b7bc4902 100644 --- a/solution/0200-0299/0207.Course Schedule/Solution.go +++ b/solution/0200-0299/0207.Course Schedule/Solution.go @@ -7,8 +7,8 @@ func canFinish(numCourses int, prerequisites [][]int) bool { indeg[a]++ } q := []int{} - for i, v := range indeg { - if v == 0 { + for i, x := range indeg { + if x == 0 { q = append(q, i) } } diff --git a/solution/0200-0299/0207.Course Schedule/Solution.py b/solution/0200-0299/0207.Course Schedule/Solution.py index 22b0989bd23e5..917d6f03827c8 100644 --- a/solution/0200-0299/0207.Course Schedule/Solution.py +++ b/solution/0200-0299/0207.Course Schedule/Solution.py @@ -6,7 +6,7 @@ def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: g[b].append(a) indeg[a] += 1 cnt = 0 - q = deque([i for i, v in enumerate(indeg) if v == 0]) + q = deque(i for i, x in enumerate(indeg) if x == 0) while q: i = q.popleft() cnt += 1 diff --git a/solution/0200-0299/0207.Course Schedule/Solution.ts b/solution/0200-0299/0207.Course Schedule/Solution.ts index 718fc84739bef..55db7895b40e2 100644 --- a/solution/0200-0299/0207.Course Schedule/Solution.ts +++ b/solution/0200-0299/0207.Course Schedule/Solution.ts @@ -1,21 +1,21 @@ function canFinish(numCourses: number, prerequisites: number[][]): boolean { - let g = Array.from({ length: numCourses }, () => []); - let indeg = new Array(numCourses).fill(0); - for (let [a, b] of prerequisites) { + const g: number[][] = new Array(numCourses).fill(0).map(() => []); + const indeg: number[] = new Array(numCourses).fill(0); + for (const [a, b] of prerequisites) { g[b].push(a); - ++indeg[a]; + indeg[a]++; } - let q = []; + const q: number[] = []; for (let i = 0; i < numCourses; ++i) { - if (!indeg[i]) { + if (indeg[i] == 0) { q.push(i); } } let cnt = 0; while (q.length) { - const i = q.shift(); - ++cnt; - for (let j of g[i]) { + const i = q.shift()!; + cnt++; + for (const j of g[i]) { if (--indeg[j] == 0) { q.push(j); } diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/README.md b/solution/0200-0299/0209.Minimum Size Subarray Sum/README.md index 97c9c5790d1a1..ee9b3d761748c 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/README.md +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/README.md @@ -58,15 +58,23 @@ **方法一:前缀和 + 二分查找** -先求出数组的前缀和 `s`,然后根据 `s[j] - s[i] >= target` => `s[j] >= s[i] + target`,找出最小的一个 j,使得 `s[j]` 满足大于等于 `s[i] + target`,然后更新最小长度即可。 +我们先预处理出数组 $nums$ 的前缀和数组 $s$,其中 $s[i]$ 表示数组 $nums$ 前 $i$ 项元素之和。由于数组 $nums$ 中的元素都是正整数,因此数组 $s$ 也是单调递增的。另外,我们初始化答案 $ans = n + 1$,其中 $n$ 为数组 $nums$ 的长度。 -时间复杂度 $O(NlogN)$。 +接下来,我们遍历前缀和数组 $s$,对于其中的每个元素 $s[i]$,我们可以通过二分查找的方法找到满足 $s[j] \geq s[i] + target$ 的最小下标 $j$,如果 $j \leq n$,则说明存在满足条件的子数组,我们可以更新答案,即 $ans = min(ans, j - i)$。 -**方法二:滑动窗口** +最后,如果 $ans \leq n$,则说明存在满足条件的子数组,返回 $ans$,否则返回 $0$。 -使用指针 `left`, `right` 分别表示子数组的开始位置和结束位置,维护变量 `sum` 表示子数组 `nums[left...right]` 元素之和。初始时 `left`, `right` 均指向 0。每一次迭代,将 `nums[right]` 加到 `sum`,如果此时 `sum >= target`,更新最小长度即可。然后将 `sum` 减去 `nums[left]`,接着 `left` 指针右移直至 `sum < target`。每一次迭代最后,将 `right` 指针右移。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。 -时间复杂度 $O(N)$。 +**方法二:双指针** + +我们可以使用双指针 $j$ 和 $i$ 维护一个窗口,其中窗口中的所有元素之和小于 $target$。初始时 $j = 0$,答案 $ans = n + 1$,其中 $n$ 为数组 $nums$ 的长度。 + +接下来,指针 $i$ 从 $0$ 开始向右移动,每次移动一步,我们将指针 $i$ 对应的元素加入窗口,同时更新窗口中元素之和。如果窗口中元素之和大于等于 $target$,说明当前子数组满足条件,我们可以更新答案,即 $ans = min(ans, i - j + 1)$。然后我们不断地从窗口中移除元素 $nums[j]$,直到窗口中元素之和小于 $target$,然后重复上述过程。 + +最后,如果 $ans \leq n$,则说明存在满足条件的子数组,返回 $ans$,否则返回 $0$。 + +时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度。 @@ -74,169 +82,172 @@ -前缀和 + 二分查找: - ```python class Solution: def minSubArrayLen(self, target: int, nums: List[int]) -> int: - s = [0] + list(accumulate(nums)) n = len(nums) + s = list(accumulate(nums, initial=0)) ans = n + 1 - for i, v in enumerate(s): - t = v + target - j = bisect_left(s, t) - if j != n + 1: + for i, x in enumerate(s): + j = bisect_left(s, x + target) + if j <= n: ans = min(ans, j - i) - return 0 if ans == n + 1 else ans + return ans if ans <= n else 0 ``` -滑动窗口: - ```python class Solution: def minSubArrayLen(self, target: int, nums: List[int]) -> int: n = len(nums) - left = right = 0 - sum, res = 0, n + 1 - while right < n: - sum += nums[right] - while sum >= target: - res = min(res, right - left + 1) - sum -= nums[left] - left += 1 - right += 1 - return 0 if res == n + 1 else res + ans = n + 1 + s = j = 0 + for i, x in enumerate(nums): + s += x + while j < n and s >= target: + ans = min(ans, i - j + 1) + s -= nums[j] + j += 1 + return ans if ans <= n else 0 ``` ### **Java** -前缀和 + 二分查找: - ```java class Solution { public int minSubArrayLen(int target, int[] nums) { int n = nums.length; - int[] s = new int[n + 1]; + long[] s = new long[n + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + nums[i]; } int ans = n + 1; - for (int i = 0; i < n; ++i) { - int t = s[i] + target; - int left = 0, right = n + 1; - while (left < right) { - int mid = (left + right) >> 1; - if (s[mid] >= t) { - right = mid; - } else { - left = mid + 1; - } + for (int i = 0; i <= n; ++i) { + int j = search(s, s[i] + target); + if (j <= n) { + ans = Math.min(ans, j - i); } - if (left != n + 1) { - ans = Math.min(ans, left - i); + } + return ans <= n ? ans : 0; + } + + private int search(long[] nums, long x) { + int l = 0, r = nums.length; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] >= x) { + r = mid; + } else { + l = mid + 1; } } - return ans == n + 1 ? 0 : ans; + return l; } } ``` -滑动窗口: - ```java class Solution { public int minSubArrayLen(int target, int[] nums) { int n = nums.length; - int left = 0, right = 0; - int sum = 0, res = n + 1; - while (right < n) { - sum += nums[right]; - while (sum >= target) { - res = Math.min(res, right - left + 1); - sum -= nums[left++]; + long s = 0; + int ans = n + 1; + for (int i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (j < n && s >= target) { + ans = Math.min(ans, i - j + 1); + s -= nums[j++]; } - ++right; } - return res == n + 1 ? 0 : res; + return ans <= n ? ans : 0; } } ``` ### **C++** -前缀和 + 二分查找: - ```cpp class Solution { public: int minSubArrayLen(int target, vector& nums) { int n = nums.size(); - vector s(n + 1); - for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i]; - int ans = n + 1; + vector s(n + 1); for (int i = 0; i < n; ++i) { - int t = s[i] + target; - auto p = lower_bound(s.begin(), s.end(), t); - if (p != s.end()) { - int j = p - s.begin(); + s[i + 1] = s[i] + nums[i]; + } + int ans = n + 1; + for (int i = 0; i <= n; ++i) { + int j = lower_bound(s.begin(), s.end(), s[i] + target) - s.begin(); + if (j <= n) { ans = min(ans, j - i); } } - return ans == n + 1 ? 0 : ans; + return ans <= n ? ans : 0; } }; ``` -滑动窗口: - ```cpp class Solution { public: int minSubArrayLen(int target, vector& nums) { - int left = 0, right; - int sum = 0; - int minlen = INT_MAX; - - for (right = 0; right < nums.size(); right++) { - sum += nums[right]; - while (left <= right && sum >= target) { - minlen = min(minlen, right - left + 1); - sum -= nums[left++]; + int n = nums.size(); + long long s = 0; + int ans = n + 1; + for (int i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (j < n && s >= target) { + ans = min(ans, i - j + 1); + s -= nums[j++]; } } - - return minlen == INT_MAX ? 0 : minlen; + return ans == n + 1 ? 0 : ans; } }; ``` ### **Go** -前缀和 + 二分查找: - ```go func minSubArrayLen(target int, nums []int) int { n := len(nums) s := make([]int, n+1) - for i, v := range nums { - s[i+1] = s[i] + v + for i, x := range nums { + s[i+1] = s[i] + x } ans := n + 1 - for i, v := range s { - t := v + target - left, right := 0, n+1 - for left < right { - mid := (left + right) >> 1 - if s[mid] >= t { - right = mid - } else { - left = mid + 1 - } + for i, x := range s { + j := sort.SearchInts(s, x+target) + if j <= n { + ans = min(ans, j-i) } - if left != n+1 && ans > left-i { - ans = left - i + } + if ans == n+1 { + return 0 + } + return ans +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + +```go +func minSubArrayLen(target int, nums []int) int { + n := len(nums) + s := 0 + ans := n + 1 + for i, j := 0, 0; i < n; i++ { + s += nums[i] + for s >= target { + ans = min(ans, i-j+1) + s -= nums[j] + j++ } } if ans == n+1 { @@ -244,29 +255,31 @@ func minSubArrayLen(target int, nums []int) int { } return ans } + +func min(a, b int) int { + if a < b { + return a + } + return b +} ``` ### **C#** -滑动窗口: - ```cs public class Solution { public int MinSubArrayLen(int target, int[] nums) { int n = nums.Length; - int left = 0, right = 0; - int sum = 0, res = n + 1; - while (right < n) - { - sum += nums[right]; - while (sum >= target) - { - res = Math.Min(res, right - left + 1); - sum -= nums[left++]; + long s = 0; + int ans = n + 1; + for (int i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (s >= target) { + ans = Math.Min(ans, i - j + 1); + s -= nums[j++]; } - ++right; } - return res == n + 1 ? 0 : res; + return ans == n + 1 ? 0 : ans; } } ``` @@ -276,22 +289,47 @@ public class Solution { ```ts function minSubArrayLen(target: number, nums: number[]): number { const n = nums.length; - let res = n + 1; - let sum = 0; - let i = 0; - for (let j = 0; j < n; j++) { - sum += nums[j]; - while (sum >= target) { - res = Math.min(res, j - i + 1); - sum -= nums[i]; - i++; + const s: number[] = new Array(n + 1).fill(0); + for (let i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + let ans = n + 1; + const search = (x: number) => { + let l = 0; + let r = n + 1; + while (l < r) { + const mid = (l + r) >>> 1; + if (s[mid] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + for (let i = 0; i <= n; ++i) { + const j = search(s[i] + target); + if (j <= n) { + ans = Math.min(ans, j - i); } } + return ans === n + 1 ? 0 : ans; +} +``` - if (res === n + 1) { - return 0; +```ts +function minSubArrayLen(target: number, nums: number[]): number { + const n = nums.length; + let s = 0; + let ans = n + 1; + for (let i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (s >= target) { + ans = Math.min(ans, i - j + 1); + s -= nums[j++]; + } } - return res; + return ans === n + 1 ? 0 : ans; } ``` diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/README_EN.md b/solution/0200-0299/0209.Minimum Size Subarray Sum/README_EN.md index ddfbd1974f7a5..37e785dcc45dd 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/README_EN.md +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/README_EN.md @@ -51,167 +51,170 @@ ### **Python3** -PreSum & Binary search: - ```python class Solution: def minSubArrayLen(self, target: int, nums: List[int]) -> int: - s = [0] + list(accumulate(nums)) n = len(nums) + s = list(accumulate(nums, initial=0)) ans = n + 1 - for i, v in enumerate(s): - t = v + target - j = bisect_left(s, t) - if j != n + 1: + for i, x in enumerate(s): + j = bisect_left(s, x + target) + if j <= n: ans = min(ans, j - i) - return 0 if ans == n + 1 else ans + return ans if ans <= n else 0 ``` -Slide window: - ```python class Solution: def minSubArrayLen(self, target: int, nums: List[int]) -> int: n = len(nums) - left = right = 0 - sum, res = 0, n + 1 - while right < n: - sum += nums[right] - while sum >= target: - res = min(res, right - left + 1) - sum -= nums[left] - left += 1 - right += 1 - return 0 if res == n + 1 else res + ans = n + 1 + s = j = 0 + for i, x in enumerate(nums): + s += x + while j < n and s >= target: + ans = min(ans, i - j + 1) + s -= nums[j] + j += 1 + return ans if ans <= n else 0 ``` ### **Java** -Presum & binary search: - ```java class Solution { public int minSubArrayLen(int target, int[] nums) { int n = nums.length; - int[] s = new int[n + 1]; + long[] s = new long[n + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + nums[i]; } int ans = n + 1; - for (int i = 0; i < n; ++i) { - int t = s[i] + target; - int left = 0, right = n + 1; - while (left < right) { - int mid = (left + right) >> 1; - if (s[mid] >= t) { - right = mid; - } else { - left = mid + 1; - } + for (int i = 0; i <= n; ++i) { + int j = search(s, s[i] + target); + if (j <= n) { + ans = Math.min(ans, j - i); } - if (left != n + 1) { - ans = Math.min(ans, left - i); + } + return ans <= n ? ans : 0; + } + + private int search(long[] nums, long x) { + int l = 0, r = nums.length; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] >= x) { + r = mid; + } else { + l = mid + 1; } } - return ans == n + 1 ? 0 : ans; + return l; } } ``` -Slide window: - ```java class Solution { public int minSubArrayLen(int target, int[] nums) { int n = nums.length; - int left = 0, right = 0; - int sum = 0, res = n + 1; - while (right < n) { - sum += nums[right]; - while (sum >= target) { - res = Math.min(res, right - left + 1); - sum -= nums[left++]; + long s = 0; + int ans = n + 1; + for (int i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (j < n && s >= target) { + ans = Math.min(ans, i - j + 1); + s -= nums[j++]; } - ++right; } - return res == n + 1 ? 0 : res; + return ans <= n ? ans : 0; } } ``` ### **C++** -Presum & binary search: - ```cpp class Solution { public: int minSubArrayLen(int target, vector& nums) { int n = nums.size(); - vector s(n + 1); - for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i]; - int ans = n + 1; + vector s(n + 1); for (int i = 0; i < n; ++i) { - int t = s[i] + target; - auto p = lower_bound(s.begin(), s.end(), t); - if (p != s.end()) { - int j = p - s.begin(); + s[i + 1] = s[i] + nums[i]; + } + int ans = n + 1; + for (int i = 0; i <= n; ++i) { + int j = lower_bound(s.begin(), s.end(), s[i] + target) - s.begin(); + if (j <= n) { ans = min(ans, j - i); } } - return ans == n + 1 ? 0 : ans; + return ans <= n ? ans : 0; } }; ``` -Slide window: - ```cpp class Solution { public: int minSubArrayLen(int target, vector& nums) { - int left = 0, right; - int sum = 0; - int minlen = INT_MAX; - - for (right = 0; right < nums.size(); right++) { - sum += nums[right]; - while (left <= right && sum >= target) { - minlen = min(minlen, right - left + 1); - sum -= nums[left++]; + int n = nums.size(); + long long s = 0; + int ans = n + 1; + for (int i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (j < n && s >= target) { + ans = min(ans, i - j + 1); + s -= nums[j++]; } } - - return minlen == INT_MAX ? 0 : minlen; + return ans == n + 1 ? 0 : ans; } }; ``` ### **Go** -Presum & binary search: - ```go func minSubArrayLen(target int, nums []int) int { n := len(nums) s := make([]int, n+1) - for i, v := range nums { - s[i+1] = s[i] + v + for i, x := range nums { + s[i+1] = s[i] + x } ans := n + 1 - for i, v := range s { - t := v + target - left, right := 0, n+1 - for left < right { - mid := (left + right) >> 1 - if s[mid] >= t { - right = mid - } else { - left = mid + 1 - } + for i, x := range s { + j := sort.SearchInts(s, x+target) + if j <= n { + ans = min(ans, j-i) } - if left != n+1 && ans > left-i { - ans = left - i + } + if ans == n+1 { + return 0 + } + return ans +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + +```go +func minSubArrayLen(target int, nums []int) int { + n := len(nums) + s := 0 + ans := n + 1 + for i, j := 0, 0; i < n; i++ { + s += nums[i] + for s >= target { + ans = min(ans, i-j+1) + s -= nums[j] + j++ } } if ans == n+1 { @@ -219,29 +222,31 @@ func minSubArrayLen(target int, nums []int) int { } return ans } + +func min(a, b int) int { + if a < b { + return a + } + return b +} ``` ### **C#** -Slide window: - ```cs public class Solution { public int MinSubArrayLen(int target, int[] nums) { int n = nums.Length; - int left = 0, right = 0; - int sum = 0, res = n + 1; - while (right < n) - { - sum += nums[right]; - while (sum >= target) - { - res = Math.Min(res, right - left + 1); - sum -= nums[left++]; + long s = 0; + int ans = n + 1; + for (int i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (s >= target) { + ans = Math.Min(ans, i - j + 1); + s -= nums[j++]; } - ++right; } - return res == n + 1 ? 0 : res; + return ans == n + 1 ? 0 : ans; } } ``` @@ -251,22 +256,47 @@ public class Solution { ```ts function minSubArrayLen(target: number, nums: number[]): number { const n = nums.length; - let res = n + 1; - let sum = 0; - let i = 0; - for (let j = 0; j < n; j++) { - sum += nums[j]; - while (sum >= target) { - res = Math.min(res, j - i + 1); - sum -= nums[i]; - i++; + const s: number[] = new Array(n + 1).fill(0); + for (let i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + let ans = n + 1; + const search = (x: number) => { + let l = 0; + let r = n + 1; + while (l < r) { + const mid = (l + r) >>> 1; + if (s[mid] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + for (let i = 0; i <= n; ++i) { + const j = search(s[i] + target); + if (j <= n) { + ans = Math.min(ans, j - i); } } + return ans === n + 1 ? 0 : ans; +} +``` - if (res === n + 1) { - return 0; +```ts +function minSubArrayLen(target: number, nums: number[]): number { + const n = nums.length; + let s = 0; + let ans = n + 1; + for (let i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (s >= target) { + ans = Math.min(ans, i - j + 1); + s -= nums[j++]; + } } - return res; + return ans === n + 1 ? 0 : ans; } ``` diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.cpp b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.cpp index ac256b44a46f3..b6d57f2aaabd5 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.cpp +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.cpp @@ -1,18 +1,16 @@ class Solution { public: int minSubArrayLen(int target, vector& nums) { - int left = 0, right; - int sum = 0; - int minlen = INT_MAX; - - for (right = 0; right < nums.size(); right++) { - sum += nums[right]; - while (left <= right && sum >= target) { - minlen = min(minlen, right - left + 1); - sum -= nums[left++]; + int n = nums.size(); + long long s = 0; + int ans = n + 1; + for (int i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (j < n && s >= target) { + ans = min(ans, i - j + 1); + s -= nums[j++]; } } - - return minlen == INT_MAX ? 0 : minlen; + return ans == n + 1 ? 0 : ans; } }; \ No newline at end of file diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.cs b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.cs index 809f3ac0dbc3c..7e86e3e907474 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.cs +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.cs @@ -1,18 +1,15 @@ public class Solution { public int MinSubArrayLen(int target, int[] nums) { int n = nums.Length; - int left = 0, right = 0; - int sum = 0, res = n + 1; - while (right < n) - { - sum += nums[right]; - while (sum >= target) - { - res = Math.Min(res, right - left + 1); - sum -= nums[left++]; + long s = 0; + int ans = n + 1; + for (int i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (s >= target) { + ans = Math.Min(ans, i - j + 1); + s -= nums[j++]; } - ++right; } - return res == n + 1 ? 0 : res; + return ans == n + 1 ? 0 : ans; } } \ No newline at end of file diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.go b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.go index 1e1589c1466da..d827df2110f06 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.go +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.go @@ -1,27 +1,24 @@ func minSubArrayLen(target int, nums []int) int { n := len(nums) - s := make([]int, n+1) - for i, v := range nums { - s[i+1] = s[i] + v - } + s := 0 ans := n + 1 - for i, v := range s { - t := v + target - left, right := 0, n+1 - for left < right { - mid := (left + right) >> 1 - if s[mid] >= t { - right = mid - } else { - left = mid + 1 - } - } - if left != n+1 && ans > left-i { - ans = left - i + for i, j := 0, 0; i < n; i++ { + s += nums[i] + for s >= target { + ans = min(ans, i-j+1) + s -= nums[j] + j++ } } if ans == n+1 { return 0 } return ans +} + +func min(a, b int) int { + if a < b { + return a + } + return b } \ No newline at end of file diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.java b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.java index e54e9d59c90e1..11b6a8155908b 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.java +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.java @@ -1,16 +1,15 @@ class Solution { public int minSubArrayLen(int target, int[] nums) { int n = nums.length; - int left = 0, right = 0; - int sum = 0, res = n + 1; - while (right < n) { - sum += nums[right]; - while (sum >= target) { - res = Math.min(res, right - left + 1); - sum -= nums[left++]; + long s = 0; + int ans = n + 1; + for (int i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (j < n && s >= target) { + ans = Math.min(ans, i - j + 1); + s -= nums[j++]; } - ++right; } - return res == n + 1 ? 0 : res; + return ans <= n ? ans : 0; } } \ No newline at end of file diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.py b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.py index fd178a45e101d..86054793f483b 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.py +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.py @@ -1,11 +1,12 @@ class Solution: def minSubArrayLen(self, target: int, nums: List[int]) -> int: - s = [0] + list(accumulate(nums)) n = len(nums) ans = n + 1 - for i, v in enumerate(s): - t = v + target - j = bisect_left(s, t) - if j != n + 1: - ans = min(ans, j - i) - return 0 if ans == n + 1 else ans + s = j = 0 + for i, x in enumerate(nums): + s += x + while j < n and s >= target: + ans = min(ans, i - j + 1) + s -= nums[j] + j += 1 + return ans if ans <= n else 0 diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.ts b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.ts index f573dbf47618e..ef54870682bf6 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.ts +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution.ts @@ -1,19 +1,13 @@ function minSubArrayLen(target: number, nums: number[]): number { const n = nums.length; - let res = n + 1; - let sum = 0; - let i = 0; - for (let j = 0; j < n; j++) { - sum += nums[j]; - while (sum >= target) { - res = Math.min(res, j - i + 1); - sum -= nums[i]; - i++; + let s = 0; + let ans = n + 1; + for (let i = 0, j = 0; i < n; ++i) { + s += nums[i]; + while (s >= target) { + ans = Math.min(ans, i - j + 1); + s -= nums[j++]; } } - - if (res === n + 1) { - return 0; - } - return res; + return ans === n + 1 ? 0 : ans; } diff --git a/solution/0200-0299/0210.Course Schedule II/README.md b/solution/0200-0299/0210.Course Schedule II/README.md index 815b287c569c5..e97614f07f28d 100644 --- a/solution/0200-0299/0210.Course Schedule II/README.md +++ b/solution/0200-0299/0210.Course Schedule II/README.md @@ -55,7 +55,15 @@ -拓扑排序,BFS 实现。 +**方法一:拓扑排序** + +对于本题,我们可以将课程看作图中的节点,先修课程看作图中的边,那么我们可以将本题转化为判断有向图中是否存在环。 + +具体地,我们可以使用拓扑排序的思想,对于每个入度为 $0$ 的节点,我们将其出度的节点的入度减 $1$,直到所有节点都被遍历到。 + +如果所有节点都被遍历到,说明图中不存在环,那么我们就可以完成所有课程的学习;否则,我们就无法完成所有课程的学习。 + +时间复杂度 $O(n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别为课程数和先修课程数。 @@ -71,8 +79,8 @@ class Solution: for a, b in prerequisites: g[b].append(a) indeg[a] += 1 - q = deque([i for i, v in enumerate(indeg) if v == 0]) ans = [] + q = deque(i for i, x in enumerate(indeg) if x == 0) while q: i = q.popleft() ans.append(i) @@ -120,36 +128,6 @@ class Solution { } ``` -### **TypeScript** - -```ts -function findOrder(numCourses: number, prerequisites: number[][]): number[] { - let g = Array.from({ length: numCourses }, () => []); - let indeg = new Array(numCourses).fill(0); - for (let [a, b] of prerequisites) { - g[b].push(a); - ++indeg[a]; - } - let q = []; - for (let i = 0; i < numCourses; ++i) { - if (!indeg[i]) { - q.push(i); - } - } - let ans = []; - while (q.length) { - const i = q.shift(); - ans.push(i); - for (let j of g[i]) { - if (--indeg[j] == 0) { - q.push(j); - } - } - } - return ans.length == numCourses ? ans : []; -} -``` - ### **C++** ```cpp @@ -164,15 +142,21 @@ public: ++indeg[a]; } queue q; - for (int i = 0; i < numCourses; ++i) - if (indeg[i] == 0) q.push(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } vector ans; while (!q.empty()) { int i = q.front(); q.pop(); ans.push_back(i); - for (int j : g[i]) - if (--indeg[j] == 0) q.push(j); + for (int j : g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } } return ans.size() == numCourses ? ans : vector(); } @@ -191,8 +175,8 @@ func findOrder(numCourses int, prerequisites [][]int) []int { indeg[a]++ } q := []int{} - for i, v := range indeg { - if v == 0 { + for i, x := range indeg { + if x == 0 { q = append(q, i) } } @@ -215,37 +199,66 @@ func findOrder(numCourses int, prerequisites [][]int) []int { } ``` +### **TypeScript** + +```ts +function findOrder(numCourses: number, prerequisites: number[][]): number[] { + const g: number[][] = new Array(numCourses).fill(0).map(() => []); + const indeg: number[] = new Array(numCourses).fill(0); + for (const [a, b] of prerequisites) { + g[b].push(a); + indeg[a]++; + } + const q: number[] = []; + for (let i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } + const ans: number[] = []; + while (q.length) { + const i = q.shift()!; + ans.push(i); + for (const j of g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } + } + return ans.length === numCourses ? ans : []; +} +``` + ### **C#** ```cs public class Solution { public int[] FindOrder(int numCourses, int[][] prerequisites) { var g = new List[numCourses]; - for (int i = 0; i < numCourses; ++i) - { + for (int i = 0; i < numCourses; ++i) { g[i] = new List(); } var indeg = new int[numCourses]; - foreach (var p in prerequisites) - { + foreach (var p in prerequisites) { int a = p[0], b = p[1]; g[b].Add(a); ++indeg[a]; } var q = new Queue(); - for (int i = 0; i < numCourses; ++i) - { - if (indeg[i] == 0) q.Enqueue(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.Enqueue(i); + } } var ans = new int[numCourses]; var cnt = 0; - while (q.Count > 0) - { + while (q.Count > 0) { int i = q.Dequeue(); ans[cnt++] = i; - foreach (int j in g[i]) - { - if (--indeg[j] == 0) q.Enqueue(j); + foreach (int j in g[i]) { + if (--indeg[j] == 0) { + q.Enqueue(j); + } } } return cnt == numCourses ? ans : new int[0]; diff --git a/solution/0200-0299/0210.Course Schedule II/README_EN.md b/solution/0200-0299/0210.Course Schedule II/README_EN.md index 2af1f04c30422..21cc874d00480 100644 --- a/solution/0200-0299/0210.Course Schedule II/README_EN.md +++ b/solution/0200-0299/0210.Course Schedule II/README_EN.md @@ -63,8 +63,8 @@ class Solution: for a, b in prerequisites: g[b].append(a) indeg[a] += 1 - q = deque([i for i, v in enumerate(indeg) if v == 0]) ans = [] + q = deque(i for i, x in enumerate(indeg) if x == 0) while q: i = q.popleft() ans.append(i) @@ -110,36 +110,6 @@ class Solution { } ``` -### **TypeScript** - -```ts -function findOrder(numCourses: number, prerequisites: number[][]): number[] { - let g = Array.from({ length: numCourses }, () => []); - let indeg = new Array(numCourses).fill(0); - for (let [a, b] of prerequisites) { - g[b].push(a); - ++indeg[a]; - } - let q = []; - for (let i = 0; i < numCourses; ++i) { - if (!indeg[i]) { - q.push(i); - } - } - let ans = []; - while (q.length) { - const i = q.shift(); - ans.push(i); - for (let j of g[i]) { - if (--indeg[j] == 0) { - q.push(j); - } - } - } - return ans.length == numCourses ? ans : []; -} -``` - ### **C++** ```cpp @@ -154,15 +124,21 @@ public: ++indeg[a]; } queue q; - for (int i = 0; i < numCourses; ++i) - if (indeg[i] == 0) q.push(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } vector ans; while (!q.empty()) { int i = q.front(); q.pop(); ans.push_back(i); - for (int j : g[i]) - if (--indeg[j] == 0) q.push(j); + for (int j : g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } } return ans.size() == numCourses ? ans : vector(); } @@ -181,8 +157,8 @@ func findOrder(numCourses int, prerequisites [][]int) []int { indeg[a]++ } q := []int{} - for i, v := range indeg { - if v == 0 { + for i, x := range indeg { + if x == 0 { q = append(q, i) } } @@ -205,37 +181,66 @@ func findOrder(numCourses int, prerequisites [][]int) []int { } ``` +### **TypeScript** + +```ts +function findOrder(numCourses: number, prerequisites: number[][]): number[] { + const g: number[][] = new Array(numCourses).fill(0).map(() => []); + const indeg: number[] = new Array(numCourses).fill(0); + for (const [a, b] of prerequisites) { + g[b].push(a); + indeg[a]++; + } + const q: number[] = []; + for (let i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } + const ans: number[] = []; + while (q.length) { + const i = q.shift()!; + ans.push(i); + for (const j of g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } + } + return ans.length === numCourses ? ans : []; +} +``` + ### **C#** ```cs public class Solution { public int[] FindOrder(int numCourses, int[][] prerequisites) { var g = new List[numCourses]; - for (int i = 0; i < numCourses; ++i) - { + for (int i = 0; i < numCourses; ++i) { g[i] = new List(); } var indeg = new int[numCourses]; - foreach (var p in prerequisites) - { + foreach (var p in prerequisites) { int a = p[0], b = p[1]; g[b].Add(a); ++indeg[a]; } var q = new Queue(); - for (int i = 0; i < numCourses; ++i) - { - if (indeg[i] == 0) q.Enqueue(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.Enqueue(i); + } } var ans = new int[numCourses]; var cnt = 0; - while (q.Count > 0) - { + while (q.Count > 0) { int i = q.Dequeue(); ans[cnt++] = i; - foreach (int j in g[i]) - { - if (--indeg[j] == 0) q.Enqueue(j); + foreach (int j in g[i]) { + if (--indeg[j] == 0) { + q.Enqueue(j); + } } } return cnt == numCourses ? ans : new int[0]; diff --git a/solution/0200-0299/0210.Course Schedule II/Solution.cpp b/solution/0200-0299/0210.Course Schedule II/Solution.cpp index ab3af7299602d..99096427714c8 100644 --- a/solution/0200-0299/0210.Course Schedule II/Solution.cpp +++ b/solution/0200-0299/0210.Course Schedule II/Solution.cpp @@ -9,15 +9,21 @@ class Solution { ++indeg[a]; } queue q; - for (int i = 0; i < numCourses; ++i) - if (indeg[i] == 0) q.push(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } vector ans; while (!q.empty()) { int i = q.front(); q.pop(); ans.push_back(i); - for (int j : g[i]) - if (--indeg[j] == 0) q.push(j); + for (int j : g[i]) { + if (--indeg[j] == 0) { + q.push(j); + } + } } return ans.size() == numCourses ? ans : vector(); } diff --git a/solution/0200-0299/0210.Course Schedule II/Solution.cs b/solution/0200-0299/0210.Course Schedule II/Solution.cs index 362c54a8a02b6..5e33944c53fb0 100644 --- a/solution/0200-0299/0210.Course Schedule II/Solution.cs +++ b/solution/0200-0299/0210.Course Schedule II/Solution.cs @@ -1,31 +1,30 @@ public class Solution { public int[] FindOrder(int numCourses, int[][] prerequisites) { var g = new List[numCourses]; - for (int i = 0; i < numCourses; ++i) - { + for (int i = 0; i < numCourses; ++i) { g[i] = new List(); } var indeg = new int[numCourses]; - foreach (var p in prerequisites) - { + foreach (var p in prerequisites) { int a = p[0], b = p[1]; g[b].Add(a); ++indeg[a]; } var q = new Queue(); - for (int i = 0; i < numCourses; ++i) - { - if (indeg[i] == 0) q.Enqueue(i); + for (int i = 0; i < numCourses; ++i) { + if (indeg[i] == 0) { + q.Enqueue(i); + } } var ans = new int[numCourses]; var cnt = 0; - while (q.Count > 0) - { + while (q.Count > 0) { int i = q.Dequeue(); ans[cnt++] = i; - foreach (int j in g[i]) - { - if (--indeg[j] == 0) q.Enqueue(j); + foreach (int j in g[i]) { + if (--indeg[j] == 0) { + q.Enqueue(j); + } } } return cnt == numCourses ? ans : new int[0]; diff --git a/solution/0200-0299/0210.Course Schedule II/Solution.go b/solution/0200-0299/0210.Course Schedule II/Solution.go index 04d5c05da6054..928a1299b47ab 100644 --- a/solution/0200-0299/0210.Course Schedule II/Solution.go +++ b/solution/0200-0299/0210.Course Schedule II/Solution.go @@ -7,8 +7,8 @@ func findOrder(numCourses int, prerequisites [][]int) []int { indeg[a]++ } q := []int{} - for i, v := range indeg { - if v == 0 { + for i, x := range indeg { + if x == 0 { q = append(q, i) } } diff --git a/solution/0200-0299/0210.Course Schedule II/Solution.py b/solution/0200-0299/0210.Course Schedule II/Solution.py index d043ce95948f7..c01e30206aa34 100644 --- a/solution/0200-0299/0210.Course Schedule II/Solution.py +++ b/solution/0200-0299/0210.Course Schedule II/Solution.py @@ -5,8 +5,8 @@ def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int for a, b in prerequisites: g[b].append(a) indeg[a] += 1 - q = deque([i for i, v in enumerate(indeg) if v == 0]) ans = [] + q = deque(i for i, x in enumerate(indeg) if x == 0) while q: i = q.popleft() ans.append(i) diff --git a/solution/0200-0299/0210.Course Schedule II/Solution.ts b/solution/0200-0299/0210.Course Schedule II/Solution.ts index ec8414f47176e..71d560e8cb77e 100644 --- a/solution/0200-0299/0210.Course Schedule II/Solution.ts +++ b/solution/0200-0299/0210.Course Schedule II/Solution.ts @@ -1,25 +1,25 @@ function findOrder(numCourses: number, prerequisites: number[][]): number[] { - let g = Array.from({ length: numCourses }, () => []); - let indeg = new Array(numCourses).fill(0); - for (let [a, b] of prerequisites) { + const g: number[][] = new Array(numCourses).fill(0).map(() => []); + const indeg: number[] = new Array(numCourses).fill(0); + for (const [a, b] of prerequisites) { g[b].push(a); - ++indeg[a]; + indeg[a]++; } - let q = []; + const q: number[] = []; for (let i = 0; i < numCourses; ++i) { - if (!indeg[i]) { + if (indeg[i] == 0) { q.push(i); } } - let ans = []; + const ans: number[] = []; while (q.length) { - const i = q.shift(); + const i = q.shift()!; ans.push(i); - for (let j of g[i]) { + for (const j of g[i]) { if (--indeg[j] == 0) { q.push(j); } } } - return ans.length == numCourses ? ans : []; + return ans.length === numCourses ? ans : []; } diff --git a/solution/0200-0299/0212.Word Search II/README.md b/solution/0200-0299/0212.Word Search II/README.md index 38224522d70fc..9fbe399177e34 100644 --- a/solution/0200-0299/0212.Word Search II/README.md +++ b/solution/0200-0299/0212.Word Search II/README.md @@ -47,6 +47,14 @@ **方法一:前缀树 + DFS** +我们首先将 `words` 中的单词构建成前缀树,前缀树的每个节点包含一个长度为 $26$ 的数组 `children`,表示该节点的子节点,数组的下标表示子节点对应的字符,数组的值表示子节点的引用。同时,每个节点还包含一个整数 `ref`,表示该节点对应的单词在 `words` 中的引用,如果该节点不是单词的结尾,则 `ref` 的值为 $-1$。 + +接下来,我们对于 `board` 中的每个单元格,从该单元格出发,进行深度优先搜索,搜索过程中,如果当前单词不是前缀树中的单词,则剪枝,如果当前单词是前缀树中的单词,则将该单词加入答案,并将该单词在前缀树中的引用置为 $-1$,表示该单词已经被找到,不需要再次搜索。 + +最后,我们将答案返回即可。 + +时间复杂度 $(m \times n \times 3^{l-1})$,空间复杂度 $(k \times l)$。其中 $m$ 和 $n$ 分别是 `board` 的行数和列数。而 $l$ 和 $k$ 分别是 `words` 中的单词的平均长度和单词的个数。 + ### **Python3** @@ -56,45 +64,46 @@ ```python class Trie: def __init__(self): - self.children = [None] * 26 - self.w = '' + self.children: List[Trie | None] = [None] * 26 + self.ref: int = -1 - def insert(self, w): + def insert(self, w: str, ref: int): node = self for c in w: idx = ord(c) - ord('a') if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] - node.w = w + node.ref = ref class Solution: def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: - def dfs(node, i, j): + def dfs(node: Trie, i: int, j: int): idx = ord(board[i][j]) - ord('a') if node.children[idx] is None: return node = node.children[idx] - if node.w: - ans.add(node.w) + if node.ref >= 0: + ans.append(words[node.ref]) + node.ref = -1 c = board[i][j] - board[i][j] = '0' - for a, b in [[0, -1], [0, 1], [1, 0], [-1, 0]]: + board[i][j] = '#' + for a, b in pairwise((-1, 0, 1, 0, -1)): x, y = i + a, j + b - if 0 <= x < m and 0 <= y < n and board[x][y] != '0': + if 0 <= x < m and 0 <= y < n and board[x][y] != '#': dfs(node, x, y) - board[i][y] = c + board[i][j] = c - trie = Trie() - for w in words: - trie.insert(w) - ans = set() + tree = Trie() + for i, w in enumerate(words): + tree.insert(w, i) m, n = len(board), len(board[0]) + ans = [] for i in range(m): for j in range(n): - dfs(trie, i, j) - return list(ans) + dfs(tree, i, j) + return ans ``` ### **Java** @@ -104,41 +113,40 @@ class Solution: ```java class Trie { Trie[] children = new Trie[26]; - String w; + int ref = -1; - void insert(String w) { + public void insert(String w, int ref) { Trie node = this; - for (char c : w.toCharArray()) { - c -= 'a'; - if (node.children[c] == null) { - node.children[c] = new Trie(); + for (int i = 0; i < w.length(); ++i) { + int j = w.charAt(i) - 'a'; + if (node.children[j] == null) { + node.children[j] = new Trie(); } - node = node.children[c]; + node = node.children[j]; } - node.w = w; + node.ref = ref; } } class Solution { - private Set ans = new HashSet<>(); - private int m; - private int n; private char[][] board; + private String[] words; + private List ans = new ArrayList<>(); public List findWords(char[][] board, String[] words) { - Trie trie = new Trie(); - for (String w : words) { - trie.insert(w); - } - m = board.length; - n = board[0].length; this.board = board; + this.words = words; + Trie tree = new Trie(); + for (int i = 0; i < words.length; ++i) { + tree.insert(words[i], i); + } + int m = board.length, n = board[0].length; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { - dfs(trie, i, j); + dfs(tree, i, j); } } - return new ArrayList<>(ans); + return ans; } private void dfs(Trie node, int i, int j) { @@ -147,15 +155,16 @@ class Solution { return; } node = node.children[idx]; - if (node.w != null) { - ans.add(node.w); + if (node.ref != -1) { + ans.add(words[node.ref]); + node.ref = -1; } char c = board[i][j]; - board[i][j] = '0'; + board[i][j] = '#'; int[] dirs = {-1, 0, 1, 0, -1}; for (int k = 0; k < 4; ++k) { int x = i + dirs[k], y = j + dirs[k + 1]; - if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0') { + if (x >= 0 && x < board.length && y >= 0 && y < board[0].length && board[x][y] != '#') { dfs(node, x, y); } } @@ -170,51 +179,63 @@ class Solution { class Trie { public: vector children; - string w; + int ref; + Trie() - : children(26) - , w("") { } + : children(26, nullptr) + , ref(-1) {} - void insert(string& w) { + void insert(const string& w, int ref) { Trie* node = this; for (char c : w) { c -= 'a'; - if (!node->children[c]) node->children[c] = new Trie(); + if (!node->children[c]) { + node->children[c] = new Trie(); + } node = node->children[c]; } - node->w = w; + node->ref = ref; } }; class Solution { public: - vector dirs = {-1, 0, 1, 0, -1}; - vector findWords(vector>& board, vector& words) { - Trie* trie = new Trie(); - unordered_set res; - for (auto& w : words) trie->insert(w); - for (int i = 0; i < board.size(); ++i) - for (int j = 0; j < board[0].size(); ++j) - dfs(trie, i, j, board, res); + Trie* tree = new Trie(); + for (int i = 0; i < words.size(); ++i) { + tree->insert(words[i], i); + } vector ans; - for (auto& w : res) ans.emplace_back(w); - return ans; - } + int m = board.size(), n = board[0].size(); - void dfs(Trie* node, int i, int j, vector>& board, unordered_set& res) { - int idx = board[i][j] - 'a'; - if (!node->children[idx]) return; - node = node->children[idx]; - if (node->w != "") res.insert(node->w); - char c = board[i][j]; - board[i][j] = '0'; + function dfs = [&](Trie* node, int i, int j) { + int idx = board[i][j] - 'a'; + if (!node->children[idx]) { + return; + } + node = node->children[idx]; + if (node->ref != -1) { + ans.emplace_back(words[node->ref]); + node->ref = -1; + } + int dirs[5] = {-1, 0, 1, 0, -1}; + char c = board[i][j]; + board[i][j] = '#'; + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#') { + dfs(node, x, y); + } + } + board[i][j] = c; + }; - for (int k = 0; k < 4; ++k) { - int x = i + dirs[k], y = j + dirs[k + 1]; - if (x >= 0 && x < board.size() && y >= 0 && y < board[0].size() && board[x][y] != '0') dfs(node, x, y, board, res); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + dfs(tree, i, j); + } } - board[i][j] = c; + return ans; } }; ``` @@ -224,62 +245,122 @@ public: ```go type Trie struct { children [26]*Trie - w string + ref int } func newTrie() *Trie { - return &Trie{} + return &Trie{ref: -1} } -func (this *Trie) insert(word string) { +func (this *Trie) insert(w string, ref int) { node := this - for _, c := range word { + for _, c := range w { c -= 'a' if node.children[c] == nil { node.children[c] = newTrie() } node = node.children[c] } - node.w = word + node.ref = ref } -func findWords(board [][]byte, words []string) []string { +func findWords(board [][]byte, words []string) (ans []string) { trie := newTrie() - for _, w := range words { - trie.insert(w) + for i, w := range words { + trie.insert(w, i) } m, n := len(board), len(board[0]) - res := map[string]bool{} - var dfs func(node *Trie, i, j int) + var dfs func(*Trie, int, int) dfs = func(node *Trie, i, j int) { idx := board[i][j] - 'a' if node.children[idx] == nil { return } node = node.children[idx] - if node.w != "" { - res[node.w] = true + if node.ref != -1 { + ans = append(ans, words[node.ref]) + node.ref = -1 } - dirs := []int{-1, 0, 1, 0, -1} c := board[i][j] - board[i][j] = '0' + board[i][j] = '#' + dirs := [5]int{-1, 0, 1, 0, -1} for k := 0; k < 4; k++ { x, y := i+dirs[k], j+dirs[k+1] - if x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0' { + if x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#' { dfs(node, x, y) } } board[i][j] = c } - for i, row := range board { - for j := range row { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { dfs(trie, i, j) } } - var ans []string - for v := range res { - ans = append(ans, v) - } - return ans + return +} +``` + +### **TypeScript** + +```ts +class Trie { + children: Trie[]; + ref: number; + + constructor() { + this.children = new Array(26); + this.ref = -1; + } + + insert(w: string, ref: number): void { + let node: Trie = this; + for (let i = 0; i < w.length; i++) { + const c = w.charCodeAt(i) - 97; + if (node.children[c] == null) { + node.children[c] = new Trie(); + } + node = node.children[c]; + } + node.ref = ref; + } +} + +function findWords(board: string[][], words: string[]): string[] { + const tree = new Trie(); + for (let i = 0; i < words.length; ++i) { + tree.insert(words[i], i); + } + const m = board.length; + const n = board[0].length; + const ans: string[] = []; + const dirs: number[] = [-1, 0, 1, 0, -1]; + const dfs = (node: Trie, i: number, j: number) => { + const idx = board[i][j].charCodeAt(0) - 97; + if (node.children[idx] == null) { + return; + } + node = node.children[idx]; + if (node.ref != -1) { + ans.push(words[node.ref]); + node.ref = -1; + } + const c = board[i][j]; + board[i][j] = '#'; + for (let k = 0; k < 4; ++k) { + const x = i + dirs[k]; + const y = j + dirs[k + 1]; + if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#') { + dfs(node, x, y); + } + } + board[i][j] = c; + }; + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + dfs(tree, i, j); + } + } + return ans; } ``` diff --git a/solution/0200-0299/0212.Word Search II/README_EN.md b/solution/0200-0299/0212.Word Search II/README_EN.md index 813da11cee9d2..df0558d62a09d 100644 --- a/solution/0200-0299/0212.Word Search II/README_EN.md +++ b/solution/0200-0299/0212.Word Search II/README_EN.md @@ -48,45 +48,46 @@ DFS. ```python class Trie: def __init__(self): - self.children = [None] * 26 - self.w = '' + self.children: List[Trie | None] = [None] * 26 + self.ref: int = -1 - def insert(self, w): + def insert(self, w: str, ref: int): node = self for c in w: idx = ord(c) - ord('a') if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] - node.w = w + node.ref = ref class Solution: def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: - def dfs(node, i, j): + def dfs(node: Trie, i: int, j: int): idx = ord(board[i][j]) - ord('a') if node.children[idx] is None: return node = node.children[idx] - if node.w: - ans.add(node.w) + if node.ref >= 0: + ans.append(words[node.ref]) + node.ref = -1 c = board[i][j] - board[i][j] = '0' - for a, b in [[0, -1], [0, 1], [1, 0], [-1, 0]]: + board[i][j] = '#' + for a, b in pairwise((-1, 0, 1, 0, -1)): x, y = i + a, j + b - if 0 <= x < m and 0 <= y < n and board[x][y] != '0': + if 0 <= x < m and 0 <= y < n and board[x][y] != '#': dfs(node, x, y) - board[i][y] = c + board[i][j] = c - trie = Trie() - for w in words: - trie.insert(w) - ans = set() + tree = Trie() + for i, w in enumerate(words): + tree.insert(w, i) m, n = len(board), len(board[0]) + ans = [] for i in range(m): for j in range(n): - dfs(trie, i, j) - return list(ans) + dfs(tree, i, j) + return ans ``` ### **Java** @@ -94,41 +95,40 @@ class Solution: ```java class Trie { Trie[] children = new Trie[26]; - String w; + int ref = -1; - void insert(String w) { + public void insert(String w, int ref) { Trie node = this; - for (char c : w.toCharArray()) { - c -= 'a'; - if (node.children[c] == null) { - node.children[c] = new Trie(); + for (int i = 0; i < w.length(); ++i) { + int j = w.charAt(i) - 'a'; + if (node.children[j] == null) { + node.children[j] = new Trie(); } - node = node.children[c]; + node = node.children[j]; } - node.w = w; + node.ref = ref; } } class Solution { - private Set ans = new HashSet<>(); - private int m; - private int n; private char[][] board; + private String[] words; + private List ans = new ArrayList<>(); public List findWords(char[][] board, String[] words) { - Trie trie = new Trie(); - for (String w : words) { - trie.insert(w); - } - m = board.length; - n = board[0].length; this.board = board; + this.words = words; + Trie tree = new Trie(); + for (int i = 0; i < words.length; ++i) { + tree.insert(words[i], i); + } + int m = board.length, n = board[0].length; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { - dfs(trie, i, j); + dfs(tree, i, j); } } - return new ArrayList<>(ans); + return ans; } private void dfs(Trie node, int i, int j) { @@ -137,15 +137,16 @@ class Solution { return; } node = node.children[idx]; - if (node.w != null) { - ans.add(node.w); + if (node.ref != -1) { + ans.add(words[node.ref]); + node.ref = -1; } char c = board[i][j]; - board[i][j] = '0'; + board[i][j] = '#'; int[] dirs = {-1, 0, 1, 0, -1}; for (int k = 0; k < 4; ++k) { int x = i + dirs[k], y = j + dirs[k + 1]; - if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0') { + if (x >= 0 && x < board.length && y >= 0 && y < board[0].length && board[x][y] != '#') { dfs(node, x, y); } } @@ -160,51 +161,63 @@ class Solution { class Trie { public: vector children; - string w; + int ref; + Trie() - : children(26) - , w("") { } + : children(26, nullptr) + , ref(-1) {} - void insert(string& w) { + void insert(const string& w, int ref) { Trie* node = this; for (char c : w) { c -= 'a'; - if (!node->children[c]) node->children[c] = new Trie(); + if (!node->children[c]) { + node->children[c] = new Trie(); + } node = node->children[c]; } - node->w = w; + node->ref = ref; } }; class Solution { public: - vector dirs = {-1, 0, 1, 0, -1}; - vector findWords(vector>& board, vector& words) { - Trie* trie = new Trie(); - unordered_set res; - for (auto& w : words) trie->insert(w); - for (int i = 0; i < board.size(); ++i) - for (int j = 0; j < board[0].size(); ++j) - dfs(trie, i, j, board, res); + Trie* tree = new Trie(); + for (int i = 0; i < words.size(); ++i) { + tree->insert(words[i], i); + } vector ans; - for (auto& w : res) ans.emplace_back(w); - return ans; - } + int m = board.size(), n = board[0].size(); - void dfs(Trie* node, int i, int j, vector>& board, unordered_set& res) { - int idx = board[i][j] - 'a'; - if (!node->children[idx]) return; - node = node->children[idx]; - if (node->w != "") res.insert(node->w); - char c = board[i][j]; - board[i][j] = '0'; + function dfs = [&](Trie* node, int i, int j) { + int idx = board[i][j] - 'a'; + if (!node->children[idx]) { + return; + } + node = node->children[idx]; + if (node->ref != -1) { + ans.emplace_back(words[node->ref]); + node->ref = -1; + } + int dirs[5] = {-1, 0, 1, 0, -1}; + char c = board[i][j]; + board[i][j] = '#'; + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#') { + dfs(node, x, y); + } + } + board[i][j] = c; + }; - for (int k = 0; k < 4; ++k) { - int x = i + dirs[k], y = j + dirs[k + 1]; - if (x >= 0 && x < board.size() && y >= 0 && y < board[0].size() && board[x][y] != '0') dfs(node, x, y, board, res); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + dfs(tree, i, j); + } } - board[i][j] = c; + return ans; } }; ``` @@ -214,62 +227,122 @@ public: ```go type Trie struct { children [26]*Trie - w string + ref int } func newTrie() *Trie { - return &Trie{} + return &Trie{ref: -1} } -func (this *Trie) insert(word string) { +func (this *Trie) insert(w string, ref int) { node := this - for _, c := range word { + for _, c := range w { c -= 'a' if node.children[c] == nil { node.children[c] = newTrie() } node = node.children[c] } - node.w = word + node.ref = ref } -func findWords(board [][]byte, words []string) []string { +func findWords(board [][]byte, words []string) (ans []string) { trie := newTrie() - for _, w := range words { - trie.insert(w) + for i, w := range words { + trie.insert(w, i) } m, n := len(board), len(board[0]) - res := map[string]bool{} - var dfs func(node *Trie, i, j int) + var dfs func(*Trie, int, int) dfs = func(node *Trie, i, j int) { idx := board[i][j] - 'a' if node.children[idx] == nil { return } node = node.children[idx] - if node.w != "" { - res[node.w] = true + if node.ref != -1 { + ans = append(ans, words[node.ref]) + node.ref = -1 } - dirs := []int{-1, 0, 1, 0, -1} c := board[i][j] - board[i][j] = '0' + board[i][j] = '#' + dirs := [5]int{-1, 0, 1, 0, -1} for k := 0; k < 4; k++ { x, y := i+dirs[k], j+dirs[k+1] - if x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0' { + if x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#' { dfs(node, x, y) } } board[i][j] = c } - for i, row := range board { - for j := range row { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { dfs(trie, i, j) } } - var ans []string - for v := range res { - ans = append(ans, v) - } - return ans + return +} +``` + +### **TypeScript** + +```ts +class Trie { + children: Trie[]; + ref: number; + + constructor() { + this.children = new Array(26); + this.ref = -1; + } + + insert(w: string, ref: number): void { + let node: Trie = this; + for (let i = 0; i < w.length; i++) { + const c = w.charCodeAt(i) - 97; + if (node.children[c] == null) { + node.children[c] = new Trie(); + } + node = node.children[c]; + } + node.ref = ref; + } +} + +function findWords(board: string[][], words: string[]): string[] { + const tree = new Trie(); + for (let i = 0; i < words.length; ++i) { + tree.insert(words[i], i); + } + const m = board.length; + const n = board[0].length; + const ans: string[] = []; + const dirs: number[] = [-1, 0, 1, 0, -1]; + const dfs = (node: Trie, i: number, j: number) => { + const idx = board[i][j].charCodeAt(0) - 97; + if (node.children[idx] == null) { + return; + } + node = node.children[idx]; + if (node.ref != -1) { + ans.push(words[node.ref]); + node.ref = -1; + } + const c = board[i][j]; + board[i][j] = '#'; + for (let k = 0; k < 4; ++k) { + const x = i + dirs[k]; + const y = j + dirs[k + 1]; + if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#') { + dfs(node, x, y); + } + } + board[i][j] = c; + }; + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + dfs(tree, i, j); + } + } + return ans; } ``` diff --git a/solution/0200-0299/0212.Word Search II/Solution.cpp b/solution/0200-0299/0212.Word Search II/Solution.cpp index 3f2528f1e5612..55424fa8e18ec 100644 --- a/solution/0200-0299/0212.Word Search II/Solution.cpp +++ b/solution/0200-0299/0212.Word Search II/Solution.cpp @@ -1,50 +1,62 @@ class Trie { public: vector children; - string w; + int ref; + Trie() - : children(26) - , w("") {} + : children(26, nullptr) + , ref(-1) {} - void insert(string& w) { + void insert(const string& w, int ref) { Trie* node = this; for (char c : w) { c -= 'a'; - if (!node->children[c]) node->children[c] = new Trie(); + if (!node->children[c]) { + node->children[c] = new Trie(); + } node = node->children[c]; } - node->w = w; + node->ref = ref; } }; class Solution { public: - vector dirs = {-1, 0, 1, 0, -1}; - vector findWords(vector>& board, vector& words) { - Trie* trie = new Trie(); - unordered_set res; - for (auto& w : words) trie->insert(w); - for (int i = 0; i < board.size(); ++i) - for (int j = 0; j < board[0].size(); ++j) - dfs(trie, i, j, board, res); + Trie* tree = new Trie(); + for (int i = 0; i < words.size(); ++i) { + tree->insert(words[i], i); + } vector ans; - for (auto& w : res) ans.emplace_back(w); - return ans; - } + int m = board.size(), n = board[0].size(); - void dfs(Trie* node, int i, int j, vector>& board, unordered_set& res) { - int idx = board[i][j] - 'a'; - if (!node->children[idx]) return; - node = node->children[idx]; - if (node->w != "") res.insert(node->w); - char c = board[i][j]; - board[i][j] = '0'; + function dfs = [&](Trie* node, int i, int j) { + int idx = board[i][j] - 'a'; + if (!node->children[idx]) { + return; + } + node = node->children[idx]; + if (node->ref != -1) { + ans.emplace_back(words[node->ref]); + node->ref = -1; + } + int dirs[5] = {-1, 0, 1, 0, -1}; + char c = board[i][j]; + board[i][j] = '#'; + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#') { + dfs(node, x, y); + } + } + board[i][j] = c; + }; - for (int k = 0; k < 4; ++k) { - int x = i + dirs[k], y = j + dirs[k + 1]; - if (x >= 0 && x < board.size() && y >= 0 && y < board[0].size() && board[x][y] != '0') dfs(node, x, y, board, res); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + dfs(tree, i, j); + } } - board[i][j] = c; + return ans; } }; \ No newline at end of file diff --git a/solution/0200-0299/0212.Word Search II/Solution.go b/solution/0200-0299/0212.Word Search II/Solution.go index 077391398df60..08b9047708783 100644 --- a/solution/0200-0299/0212.Word Search II/Solution.go +++ b/solution/0200-0299/0212.Word Search II/Solution.go @@ -1,59 +1,55 @@ type Trie struct { children [26]*Trie - w string + ref int } func newTrie() *Trie { - return &Trie{} + return &Trie{ref: -1} } -func (this *Trie) insert(word string) { +func (this *Trie) insert(w string, ref int) { node := this - for _, c := range word { + for _, c := range w { c -= 'a' if node.children[c] == nil { node.children[c] = newTrie() } node = node.children[c] } - node.w = word + node.ref = ref } -func findWords(board [][]byte, words []string) []string { +func findWords(board [][]byte, words []string) (ans []string) { trie := newTrie() - for _, w := range words { - trie.insert(w) + for i, w := range words { + trie.insert(w, i) } m, n := len(board), len(board[0]) - res := map[string]bool{} - var dfs func(node *Trie, i, j int) + var dfs func(*Trie, int, int) dfs = func(node *Trie, i, j int) { idx := board[i][j] - 'a' if node.children[idx] == nil { return } node = node.children[idx] - if node.w != "" { - res[node.w] = true + if node.ref != -1 { + ans = append(ans, words[node.ref]) + node.ref = -1 } - dirs := []int{-1, 0, 1, 0, -1} c := board[i][j] - board[i][j] = '0' + board[i][j] = '#' + dirs := [5]int{-1, 0, 1, 0, -1} for k := 0; k < 4; k++ { x, y := i+dirs[k], j+dirs[k+1] - if x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0' { + if x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#' { dfs(node, x, y) } } board[i][j] = c } - for i, row := range board { - for j := range row { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { dfs(trie, i, j) } } - var ans []string - for v := range res { - ans = append(ans, v) - } - return ans + return } \ No newline at end of file diff --git a/solution/0200-0299/0212.Word Search II/Solution.java b/solution/0200-0299/0212.Word Search II/Solution.java index e82af05025d1f..8f946d994a716 100644 --- a/solution/0200-0299/0212.Word Search II/Solution.java +++ b/solution/0200-0299/0212.Word Search II/Solution.java @@ -1,40 +1,39 @@ class Trie { Trie[] children = new Trie[26]; - String w; + int ref = -1; - void insert(String w) { + public void insert(String w, int ref) { Trie node = this; - for (char c : w.toCharArray()) { - c -= 'a'; - if (node.children[c] == null) { - node.children[c] = new Trie(); + for (int i = 0; i < w.length(); ++i) { + int j = w.charAt(i) - 'a'; + if (node.children[j] == null) { + node.children[j] = new Trie(); } - node = node.children[c]; + node = node.children[j]; } - node.w = w; + node.ref = ref; } } class Solution { - private Set ans = new HashSet<>(); - private int m; - private int n; private char[][] board; + private String[] words; + private List ans = new ArrayList<>(); public List findWords(char[][] board, String[] words) { - Trie trie = new Trie(); - for (String w : words) { - trie.insert(w); - } - m = board.length; - n = board[0].length; this.board = board; + this.words = words; + Trie tree = new Trie(); + for (int i = 0; i < words.length; ++i) { + tree.insert(words[i], i); + } + int m = board.length, n = board[0].length; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { - dfs(trie, i, j); + dfs(tree, i, j); } } - return new ArrayList<>(ans); + return ans; } private void dfs(Trie node, int i, int j) { @@ -43,15 +42,16 @@ private void dfs(Trie node, int i, int j) { return; } node = node.children[idx]; - if (node.w != null) { - ans.add(node.w); + if (node.ref != -1) { + ans.add(words[node.ref]); + node.ref = -1; } char c = board[i][j]; - board[i][j] = '0'; + board[i][j] = '#'; int[] dirs = {-1, 0, 1, 0, -1}; for (int k = 0; k < 4; ++k) { int x = i + dirs[k], y = j + dirs[k + 1]; - if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0') { + if (x >= 0 && x < board.length && y >= 0 && y < board[0].length && board[x][y] != '#') { dfs(node, x, y); } } diff --git a/solution/0200-0299/0212.Word Search II/Solution.py b/solution/0200-0299/0212.Word Search II/Solution.py index 9135d51acb72c..86a138fc57e62 100644 --- a/solution/0200-0299/0212.Word Search II/Solution.py +++ b/solution/0200-0299/0212.Word Search II/Solution.py @@ -1,41 +1,42 @@ class Trie: def __init__(self): - self.children = [None] * 26 - self.w = '' + self.children: List[Trie | None] = [None] * 26 + self.ref: int = -1 - def insert(self, w): + def insert(self, w: str, ref: int): node = self for c in w: idx = ord(c) - ord('a') if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] - node.w = w + node.ref = ref class Solution: def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: - def dfs(node, i, j): + def dfs(node: Trie, i: int, j: int): idx = ord(board[i][j]) - ord('a') if node.children[idx] is None: return node = node.children[idx] - if node.w: - ans.add(node.w) + if node.ref >= 0: + ans.append(words[node.ref]) + node.ref = -1 c = board[i][j] - board[i][j] = '0' - for a, b in [[0, -1], [0, 1], [1, 0], [-1, 0]]: + board[i][j] = '#' + for a, b in pairwise((-1, 0, 1, 0, -1)): x, y = i + a, j + b - if 0 <= x < m and 0 <= y < n and board[x][y] != '0': + if 0 <= x < m and 0 <= y < n and board[x][y] != '#': dfs(node, x, y) - board[i][y] = c + board[i][j] = c - trie = Trie() - for w in words: - trie.insert(w) - ans = set() + tree = Trie() + for i, w in enumerate(words): + tree.insert(w, i) m, n = len(board), len(board[0]) + ans = [] for i in range(m): for j in range(n): - dfs(trie, i, j) - return list(ans) + dfs(tree, i, j) + return ans diff --git a/solution/0200-0299/0212.Word Search II/Solution.ts b/solution/0200-0299/0212.Word Search II/Solution.ts new file mode 100644 index 0000000000000..035e6711f6b8e --- /dev/null +++ b/solution/0200-0299/0212.Word Search II/Solution.ts @@ -0,0 +1,59 @@ +class Trie { + children: Trie[]; + ref: number; + + constructor() { + this.children = new Array(26); + this.ref = -1; + } + + insert(w: string, ref: number): void { + let node: Trie = this; + for (let i = 0; i < w.length; i++) { + const c = w.charCodeAt(i) - 97; + if (node.children[c] == null) { + node.children[c] = new Trie(); + } + node = node.children[c]; + } + node.ref = ref; + } +} + +function findWords(board: string[][], words: string[]): string[] { + const tree = new Trie(); + for (let i = 0; i < words.length; ++i) { + tree.insert(words[i], i); + } + const m = board.length; + const n = board[0].length; + const ans: string[] = []; + const dirs: number[] = [-1, 0, 1, 0, -1]; + const dfs = (node: Trie, i: number, j: number) => { + const idx = board[i][j].charCodeAt(0) - 97; + if (node.children[idx] == null) { + return; + } + node = node.children[idx]; + if (node.ref != -1) { + ans.push(words[node.ref]); + node.ref = -1; + } + const c = board[i][j]; + board[i][j] = '#'; + for (let k = 0; k < 4; ++k) { + const x = i + dirs[k]; + const y = j + dirs[k + 1]; + if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#') { + dfs(node, x, y); + } + } + board[i][j] = c; + }; + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + dfs(tree, i, j); + } + } + return ans; +} diff --git a/solution/0200-0299/0223.Rectangle Area/README.md b/solution/0200-0299/0223.Rectangle Area/README.md index fdd0deb595051..5be0ae8f16be7 100644 --- a/solution/0200-0299/0223.Rectangle Area/README.md +++ b/solution/0200-0299/0223.Rectangle Area/README.md @@ -45,7 +45,11 @@ -计算重叠部分的面积,注意考虑没有重叠的情况 +**方法一:计算重叠面积** + +我们先计算出两个矩形各自的面积,记为 $a$ 和 $b$,然后计算重叠的宽度 $width$ 和高度 $height$,那么重叠的面积为 $max(width, 0) \times max(height, 0)$,最后将 $a$, $b$ 和重叠面积相减即可。 + +时间复杂度 $O(1)$,空间复杂度 $O(1)$。 @@ -130,6 +134,41 @@ func min(a, b int) int { } ``` +### **TypeScript** + +```ts +function computeArea( + ax1: number, + ay1: number, + ax2: number, + ay2: number, + bx1: number, + by1: number, + bx2: number, + by2: number, +): number { + const a = (ax2 - ax1) * (ay2 - ay1); + const b = (bx2 - bx1) * (by2 - by1); + const width = Math.min(ax2, bx2) - Math.max(ax1, bx1); + const height = Math.min(ay2, by2) - Math.max(ay1, by1); + return a + b - Math.max(width, 0) * Math.max(height, 0); +} +``` + +### **C#** + +```cs +public class Solution { + public int ComputeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) { + int a = (ax2 - ax1) * (ay2 - ay1); + int b = (bx2 - bx1) * (by2 - by1); + int width = Math.Min(ax2, bx2) - Math.Max(ax1, bx1); + int height = Math.Min(ay2, by2) - Math.Max(ay1, by1); + return a + b - Math.Max(height, 0) * Math.Max(width, 0); + } +} +``` + ### **...** ``` diff --git a/solution/0200-0299/0223.Rectangle Area/README_EN.md b/solution/0200-0299/0223.Rectangle Area/README_EN.md index 7d7a2f89dba29..22f4a7c22c0b8 100644 --- a/solution/0200-0299/0223.Rectangle Area/README_EN.md +++ b/solution/0200-0299/0223.Rectangle Area/README_EN.md @@ -116,6 +116,41 @@ func min(a, b int) int { } ``` +### **TypeScript** + +```ts +function computeArea( + ax1: number, + ay1: number, + ax2: number, + ay2: number, + bx1: number, + by1: number, + bx2: number, + by2: number, +): number { + const a = (ax2 - ax1) * (ay2 - ay1); + const b = (bx2 - bx1) * (by2 - by1); + const width = Math.min(ax2, bx2) - Math.max(ax1, bx1); + const height = Math.min(ay2, by2) - Math.max(ay1, by1); + return a + b - Math.max(width, 0) * Math.max(height, 0); +} +``` + +### **C#** + +```cs +public class Solution { + public int ComputeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) { + int a = (ax2 - ax1) * (ay2 - ay1); + int b = (bx2 - bx1) * (by2 - by1); + int width = Math.Min(ax2, bx2) - Math.Max(ax1, bx1); + int height = Math.Min(ay2, by2) - Math.Max(ay1, by1); + return a + b - Math.Max(height, 0) * Math.Max(width, 0); + } +} +``` + ### **...** ``` diff --git a/solution/0200-0299/0223.Rectangle Area/Solution.cs b/solution/0200-0299/0223.Rectangle Area/Solution.cs index 73410231b7eb5..4e5561f3edf24 100644 --- a/solution/0200-0299/0223.Rectangle Area/Solution.cs +++ b/solution/0200-0299/0223.Rectangle Area/Solution.cs @@ -1,20 +1,9 @@ -// https://leetcode.com/problems/rectangle-area/ - -using System; - -public partial class Solution -{ - public int ComputeArea(int A, int B, int C, int D, int E, int F, int G, int H) - { - var area = (long)(C - A) * (D - B) + (G - E) * (H - F); - var overlapA = Math.Max(A, E); - var overlapB = Math.Max(B, F); - var overlapC = Math.Min(C, G); - var overlapD = Math.Min(D, H); - if (overlapA < overlapC && overlapB < overlapD) - { - area -= (overlapC - overlapA) * (overlapD - overlapB); - } - return (int)area; +public class Solution { + public int ComputeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) { + int a = (ax2 - ax1) * (ay2 - ay1); + int b = (bx2 - bx1) * (by2 - by1); + int width = Math.Min(ax2, bx2) - Math.Max(ax1, bx1); + int height = Math.Min(ay2, by2) - Math.Max(ay1, by1); + return a + b - Math.Max(height, 0) * Math.Max(width, 0); } } \ No newline at end of file diff --git a/solution/0200-0299/0223.Rectangle Area/Solution.ts b/solution/0200-0299/0223.Rectangle Area/Solution.ts new file mode 100644 index 0000000000000..9054b81ef9c8b --- /dev/null +++ b/solution/0200-0299/0223.Rectangle Area/Solution.ts @@ -0,0 +1,16 @@ +function computeArea( + ax1: number, + ay1: number, + ax2: number, + ay2: number, + bx1: number, + by1: number, + bx2: number, + by2: number, +): number { + const a = (ax2 - ax1) * (ay2 - ay1); + const b = (bx2 - bx1) * (by2 - by1); + const width = Math.min(ax2, bx2) - Math.max(ax1, bx1); + const height = Math.min(ay2, by2) - Math.max(ay1, by1); + return a + b - Math.max(width, 0) * Math.max(height, 0); +} diff --git a/solution/0200-0299/0225.Implement Stack using Queues/README.md b/solution/0200-0299/0225.Implement Stack using Queues/README.md index df2ccd7d4860a..98471c20c6487 100644 --- a/solution/0200-0299/0225.Implement Stack using Queues/README.md +++ b/solution/0200-0299/0225.Implement Stack using Queues/README.md @@ -64,6 +64,17 @@ myStack.empty(); // 返回 False +**方法一:两个队列** + +我们使用两个队列 $q_1$ 和 $q_2$,其中 $q_1$ 用于存储栈中的元素,而 $q_2$ 用于辅助实现栈的操作。 + +- `push` 操作:将元素压入 $q_2$,然后将 $q_1$ 中的元素依次弹出并压入 $q_2$,最后交换 $q_1$ 和 $q_2$ 的引用。时间复杂度 $O(n)$。 +- `pop` 操作:直接弹出 $q_1$ 的队首元素。时间复杂度 $O(1)$。 +- `top` 操作:直接返回 $q_1$ 的队首元素。时间复杂度 $O(1)$。 +- `empty` 操作:判断 $q_1$ 是否为空。时间复杂度 $O(1)$。 + +空间复杂度 $O(n)$,其中 $n$ 是栈中元素的个数。 + ### **Python3** @@ -72,38 +83,25 @@ myStack.empty(); // 返回 False ```python class MyStack: + def __init__(self): - """ - Initialize your data structure here. - """ - self.q = [] + self.q1 = deque() + self.q2 = deque() def push(self, x: int) -> None: - """ - Push element x onto stack. - """ - self.q.append(x) - n = len(self.q) - for i in range(1, n): - self.q.append(self.q.pop(0)) + self.q2.append(x) + while self.q1: + self.q2.append(self.q1.popleft()) + self.q1, self.q2 = self.q2, self.q1 def pop(self) -> int: - """ - Removes the element on top of the stack and returns that element. - """ - return self.q.pop(0) + return self.q1.popleft() def top(self) -> int: - """ - Get the top element. - """ - return self.q[0] + return self.q1[0] def empty(self) -> bool: - """ - Returns whether the stack is empty. - """ - return len(self.q) == 0 + return len(self.q1) == 0 # Your MyStack object will be instantiated and called as such: @@ -119,37 +117,36 @@ class MyStack: ```java -class MyStack { +import java.util.Deque; - private Deque q; +class MyStack { + private Deque q1 = new ArrayDeque<>(); + private Deque q2 = new ArrayDeque<>(); - /** Initialize your data structure here. */ public MyStack() { - q = new ArrayDeque<>(); + } - /** Push element x onto stack. */ public void push(int x) { - q.offerLast(x); - int n = q.size(); - while (n-- > 1) { - q.offerLast(q.pollFirst()); + q2.offer(x); + while (!q1.isEmpty()) { + q2.offer(q1.poll()); } + Deque q = q1; + q1 = q2; + q2 = q; } - /** Removes the element on top of the stack and returns that element. */ public int pop() { - return q.pollFirst(); + return q1.poll(); } - /** Get the top element. */ public int top() { - return q.peekFirst(); + return q1.peek(); } - /** Returns whether the stack is empty. */ public boolean empty() { - return q.isEmpty(); + return q1.isEmpty(); } } @@ -163,6 +160,138 @@ class MyStack { */ ``` +### **C++** + +```cpp +class MyStack { +public: + MyStack() { + + } + + void push(int x) { + q2.push(x); + while (!q1.empty()) { + q2.push(q1.front()); + q1.pop(); + } + swap(q1, q2); + } + + int pop() { + int x = q1.front(); + q1.pop(); + return x; + } + + int top() { + return q1.front(); + } + + bool empty() { + return q1.empty(); + } + +private: + queue q1; + queue q2; +}; + +/** + * Your MyStack object will be instantiated and called as such: + * MyStack* obj = new MyStack(); + * obj->push(x); + * int param_2 = obj->pop(); + * int param_3 = obj->top(); + * bool param_4 = obj->empty(); + */ +``` + +### **Go** + +```go +type MyStack struct { + q1 []int + q2 []int +} + +func Constructor() MyStack { + return MyStack{} +} + +func (this *MyStack) Push(x int) { + this.q2 = append(this.q2, x) + for len(this.q1) > 0 { + this.q2 = append(this.q2, this.q1[0]) + this.q1 = this.q1[1:] + } + this.q1, this.q2 = this.q2, this.q1 +} + +func (this *MyStack) Pop() int { + x := this.q1[0] + this.q1 = this.q1[1:] + return x +} + +func (this *MyStack) Top() int { + return this.q1[0] +} + +func (this *MyStack) Empty() bool { + return len(this.q1) == 0 +} + +/** + * Your MyStack object will be instantiated and called as such: + * obj := Constructor(); + * obj.Push(x); + * param_2 := obj.Pop(); + * param_3 := obj.Top(); + * param_4 := obj.Empty(); + */ +``` + +### **TypeScript** + +```ts +class MyStack { + q1: number[] = []; + q2: number[] = []; + + constructor() {} + + push(x: number): void { + this.q2.push(x); + while (this.q1.length) { + this.q2.push(this.q1.shift()!); + } + [this.q1, this.q2] = [this.q2, this.q1]; + } + + pop(): number { + return this.q1.shift()!; + } + + top(): number { + return this.q1[0]; + } + + empty(): boolean { + return this.q1.length === 0; + } +} + +/** + * Your MyStack object will be instantiated and called as such: + * var obj = new MyStack() + * obj.push(x) + * var param_2 = obj.pop() + * var param_3 = obj.top() + * var param_4 = obj.empty() + */ +``` + ### **...** ``` diff --git a/solution/0200-0299/0225.Implement Stack using Queues/README_EN.md b/solution/0200-0299/0225.Implement Stack using Queues/README_EN.md index f5d9104243ba6..e9f552a040b8b 100644 --- a/solution/0200-0299/0225.Implement Stack using Queues/README_EN.md +++ b/solution/0200-0299/0225.Implement Stack using Queues/README_EN.md @@ -61,38 +61,25 @@ myStack.empty(); // return False ```python class MyStack: + def __init__(self): - """ - Initialize your data structure here. - """ - self.q = [] + self.q1 = deque() + self.q2 = deque() def push(self, x: int) -> None: - """ - Push element x onto stack. - """ - self.q.append(x) - n = len(self.q) - for i in range(1, n): - self.q.append(self.q.pop(0)) + self.q2.append(x) + while self.q1: + self.q2.append(self.q1.popleft()) + self.q1, self.q2 = self.q2, self.q1 def pop(self) -> int: - """ - Removes the element on top of the stack and returns that element. - """ - return self.q.pop(0) + return self.q1.popleft() def top(self) -> int: - """ - Get the top element. - """ - return self.q[0] + return self.q1[0] def empty(self) -> bool: - """ - Returns whether the stack is empty. - """ - return len(self.q) == 0 + return len(self.q1) == 0 # Your MyStack object will be instantiated and called as such: @@ -106,37 +93,36 @@ class MyStack: ### **Java** ```java -class MyStack { +import java.util.Deque; - private Deque q; +class MyStack { + private Deque q1 = new ArrayDeque<>(); + private Deque q2 = new ArrayDeque<>(); - /** Initialize your data structure here. */ public MyStack() { - q = new ArrayDeque<>(); - } - /** Push element x onto stack. */ + } + public void push(int x) { - q.offerLast(x); - int n = q.size(); - while (n-- > 1) { - q.offerLast(q.pollFirst()); + q2.offer(x); + while (!q1.isEmpty()) { + q2.offer(q1.poll()); } + Deque q = q1; + q1 = q2; + q2 = q; } - - /** Removes the element on top of the stack and returns that element. */ + public int pop() { - return q.pollFirst(); + return q1.poll(); } - - /** Get the top element. */ + public int top() { - return q.peekFirst(); + return q1.peek(); } - - /** Returns whether the stack is empty. */ + public boolean empty() { - return q.isEmpty(); + return q1.isEmpty(); } } @@ -150,6 +136,138 @@ class MyStack { */ ``` +### **C++** + +```cpp +class MyStack { +public: + MyStack() { + + } + + void push(int x) { + q2.push(x); + while (!q1.empty()) { + q2.push(q1.front()); + q1.pop(); + } + swap(q1, q2); + } + + int pop() { + int x = q1.front(); + q1.pop(); + return x; + } + + int top() { + return q1.front(); + } + + bool empty() { + return q1.empty(); + } + +private: + queue q1; + queue q2; +}; + +/** + * Your MyStack object will be instantiated and called as such: + * MyStack* obj = new MyStack(); + * obj->push(x); + * int param_2 = obj->pop(); + * int param_3 = obj->top(); + * bool param_4 = obj->empty(); + */ +``` + +### **Go** + +```go +type MyStack struct { + q1 []int + q2 []int +} + +func Constructor() MyStack { + return MyStack{} +} + +func (this *MyStack) Push(x int) { + this.q2 = append(this.q2, x) + for len(this.q1) > 0 { + this.q2 = append(this.q2, this.q1[0]) + this.q1 = this.q1[1:] + } + this.q1, this.q2 = this.q2, this.q1 +} + +func (this *MyStack) Pop() int { + x := this.q1[0] + this.q1 = this.q1[1:] + return x +} + +func (this *MyStack) Top() int { + return this.q1[0] +} + +func (this *MyStack) Empty() bool { + return len(this.q1) == 0 +} + +/** + * Your MyStack object will be instantiated and called as such: + * obj := Constructor(); + * obj.Push(x); + * param_2 := obj.Pop(); + * param_3 := obj.Top(); + * param_4 := obj.Empty(); + */ +``` + +### **TypeScript** + +```ts +class MyStack { + q1: number[] = []; + q2: number[] = []; + + constructor() {} + + push(x: number): void { + this.q2.push(x); + while (this.q1.length) { + this.q2.push(this.q1.shift()!); + } + [this.q1, this.q2] = [this.q2, this.q1]; + } + + pop(): number { + return this.q1.shift()!; + } + + top(): number { + return this.q1[0]; + } + + empty(): boolean { + return this.q1.length === 0; + } +} + +/** + * Your MyStack object will be instantiated and called as such: + * var obj = new MyStack() + * obj.push(x) + * var param_2 = obj.pop() + * var param_3 = obj.top() + * var param_4 = obj.empty() + */ +``` + ### **...** ``` diff --git a/solution/0200-0299/0225.Implement Stack using Queues/Solution.cpp b/solution/0200-0299/0225.Implement Stack using Queues/Solution.cpp new file mode 100644 index 0000000000000..176e945a9f097 --- /dev/null +++ b/solution/0200-0299/0225.Implement Stack using Queues/Solution.cpp @@ -0,0 +1,42 @@ +class MyStack { +public: + MyStack() { + + } + + void push(int x) { + q2.push(x); + while (!q1.empty()) { + q2.push(q1.front()); + q1.pop(); + } + swap(q1, q2); + } + + int pop() { + int x = q1.front(); + q1.pop(); + return x; + } + + int top() { + return q1.front(); + } + + bool empty() { + return q1.empty(); + } + +private: + queue q1; + queue q2; +}; + +/** + * Your MyStack object will be instantiated and called as such: + * MyStack* obj = new MyStack(); + * obj->push(x); + * int param_2 = obj->pop(); + * int param_3 = obj->top(); + * bool param_4 = obj->empty(); + */ \ No newline at end of file diff --git a/solution/0200-0299/0225.Implement Stack using Queues/Solution.go b/solution/0200-0299/0225.Implement Stack using Queues/Solution.go new file mode 100644 index 0000000000000..29e7eecd420f1 --- /dev/null +++ b/solution/0200-0299/0225.Implement Stack using Queues/Solution.go @@ -0,0 +1,40 @@ +type MyStack struct { + q1 []int + q2 []int +} + +func Constructor() MyStack { + return MyStack{} +} + +func (this *MyStack) Push(x int) { + this.q2 = append(this.q2, x) + for len(this.q1) > 0 { + this.q2 = append(this.q2, this.q1[0]) + this.q1 = this.q1[1:] + } + this.q1, this.q2 = this.q2, this.q1 +} + +func (this *MyStack) Pop() int { + x := this.q1[0] + this.q1 = this.q1[1:] + return x +} + +func (this *MyStack) Top() int { + return this.q1[0] +} + +func (this *MyStack) Empty() bool { + return len(this.q1) == 0 +} + +/** + * Your MyStack object will be instantiated and called as such: + * obj := Constructor(); + * obj.Push(x); + * param_2 := obj.Pop(); + * param_3 := obj.Top(); + * param_4 := obj.Empty(); + */ \ No newline at end of file diff --git a/solution/0200-0299/0225.Implement Stack using Queues/Solution.java b/solution/0200-0299/0225.Implement Stack using Queues/Solution.java index f02f81a77bdfa..4c1a60af8fe18 100644 --- a/solution/0200-0299/0225.Implement Stack using Queues/Solution.java +++ b/solution/0200-0299/0225.Implement Stack using Queues/Solution.java @@ -1,34 +1,33 @@ -class MyStack { +import java.util.Deque; - private Deque q; +class MyStack { + private Deque q1 = new ArrayDeque<>(); + private Deque q2 = new ArrayDeque<>(); - /** Initialize your data structure here. */ public MyStack() { - q = new ArrayDeque<>(); - } - /** Push element x onto stack. */ + } + public void push(int x) { - q.offerLast(x); - int n = q.size(); - while (n-- > 1) { - q.offerLast(q.pollFirst()); + q2.offer(x); + while (!q1.isEmpty()) { + q2.offer(q1.poll()); } + Deque q = q1; + q1 = q2; + q2 = q; } - - /** Removes the element on top of the stack and returns that element. */ + public int pop() { - return q.pollFirst(); + return q1.poll(); } - - /** Get the top element. */ + public int top() { - return q.peekFirst(); + return q1.peek(); } - - /** Returns whether the stack is empty. */ + public boolean empty() { - return q.isEmpty(); + return q1.isEmpty(); } } diff --git a/solution/0200-0299/0225.Implement Stack using Queues/Solution.py b/solution/0200-0299/0225.Implement Stack using Queues/Solution.py index 14bbad01f26f7..acfb00a48af08 100644 --- a/solution/0200-0299/0225.Implement Stack using Queues/Solution.py +++ b/solution/0200-0299/0225.Implement Stack using Queues/Solution.py @@ -1,36 +1,23 @@ class MyStack: + def __init__(self): - """ - Initialize your data structure here. - """ - self.q = [] + self.q1 = deque() + self.q2 = deque() def push(self, x: int) -> None: - """ - Push element x onto stack. - """ - self.q.append(x) - n = len(self.q) - for i in range(1, n): - self.q.append(self.q.pop(0)) + self.q2.append(x) + while self.q1: + self.q2.append(self.q1.popleft()) + self.q1, self.q2 = self.q2, self.q1 def pop(self) -> int: - """ - Removes the element on top of the stack and returns that element. - """ - return self.q.pop(0) + return self.q1.popleft() def top(self) -> int: - """ - Get the top element. - """ - return self.q[0] + return self.q1[0] def empty(self) -> bool: - """ - Returns whether the stack is empty. - """ - return len(self.q) == 0 + return len(self.q1) == 0 # Your MyStack object will be instantiated and called as such: diff --git a/solution/0200-0299/0225.Implement Stack using Queues/Solution.ts b/solution/0200-0299/0225.Implement Stack using Queues/Solution.ts new file mode 100644 index 0000000000000..4189fc9a3e009 --- /dev/null +++ b/solution/0200-0299/0225.Implement Stack using Queues/Solution.ts @@ -0,0 +1,35 @@ +class MyStack { + q1: number[] = []; + q2: number[] = []; + + constructor() {} + + push(x: number): void { + this.q2.push(x); + while (this.q1.length) { + this.q2.push(this.q1.shift()!); + } + [this.q1, this.q2] = [this.q2, this.q1]; + } + + pop(): number { + return this.q1.shift()!; + } + + top(): number { + return this.q1[0]; + } + + empty(): boolean { + return this.q1.length === 0; + } +} + +/** + * Your MyStack object will be instantiated and called as such: + * var obj = new MyStack() + * obj.push(x) + * var param_2 = obj.pop() + * var param_3 = obj.top() + * var param_4 = obj.empty() + */ diff --git a/solution/0200-0299/0226.Invert Binary Tree/README.md b/solution/0200-0299/0226.Invert Binary Tree/README.md index f84df43361aef..7f2e727651ee8 100644 --- a/solution/0200-0299/0226.Invert Binary Tree/README.md +++ b/solution/0200-0299/0226.Invert Binary Tree/README.md @@ -48,7 +48,11 @@ -DFS。 +**方法一:递归** + +递归的思路很简单,就是交换当前节点的左右子树,然后递归地交换当前节点的左右子树。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。 @@ -64,7 +68,7 @@ DFS。 # self.left = left # self.right = right class Solution: - def invertTree(self, root: TreeNode) -> TreeNode: + def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: def dfs(root): if root is None: return @@ -132,18 +136,17 @@ class Solution { class Solution { public: TreeNode* invertTree(TreeNode* root) { + function dfs = [&](TreeNode* root) { + if (!root) { + return; + } + swap(root->left, root->right); + dfs(root->left); + dfs(root->right); + }; dfs(root); return root; } - - void dfs(TreeNode* root) { - if (!root) return; - TreeNode* t = root->left; - root->left = root->right; - root->right = t; - dfs(root->left); - dfs(root->right); - } }; ``` @@ -159,7 +162,7 @@ public: * } */ func invertTree(root *TreeNode) *TreeNode { - var dfs func(root *TreeNode) + var dfs func(*TreeNode) dfs = func(root *TreeNode) { if root == nil { return @@ -189,17 +192,50 @@ func invertTree(root *TreeNode) *TreeNode { * @return {TreeNode} */ var invertTree = function (root) { - function dfs(root) { - if (!root) return; + const dfs = root => { + if (!root) { + return; + } [root.left, root.right] = [root.right, root.left]; dfs(root.left); dfs(root.right); - } + }; dfs(root); return root; }; ``` +### **TypeScript** + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function invertTree(root: TreeNode | null): TreeNode | null { + const dfs = (root: TreeNode | null) => { + if (root === null) { + return; + } + [root.left, root.right] = [root.right, root.left]; + dfs(root.left); + dfs(root.right); + }; + dfs(root); + return root; +} +``` + ### **...** ``` diff --git a/solution/0200-0299/0226.Invert Binary Tree/README_EN.md b/solution/0200-0299/0226.Invert Binary Tree/README_EN.md index 8240f4a1d1d71..e6a2cfe18bff3 100644 --- a/solution/0200-0299/0226.Invert Binary Tree/README_EN.md +++ b/solution/0200-0299/0226.Invert Binary Tree/README_EN.md @@ -52,7 +52,7 @@ DFS. # self.left = left # self.right = right class Solution: - def invertTree(self, root: TreeNode) -> TreeNode: + def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: def dfs(root): if root is None: return @@ -118,18 +118,17 @@ class Solution { class Solution { public: TreeNode* invertTree(TreeNode* root) { + function dfs = [&](TreeNode* root) { + if (!root) { + return; + } + swap(root->left, root->right); + dfs(root->left); + dfs(root->right); + }; dfs(root); return root; } - - void dfs(TreeNode* root) { - if (!root) return; - TreeNode* t = root->left; - root->left = root->right; - root->right = t; - dfs(root->left); - dfs(root->right); - } }; ``` @@ -145,7 +144,7 @@ public: * } */ func invertTree(root *TreeNode) *TreeNode { - var dfs func(root *TreeNode) + var dfs func(*TreeNode) dfs = func(root *TreeNode) { if root == nil { return @@ -175,17 +174,50 @@ func invertTree(root *TreeNode) *TreeNode { * @return {TreeNode} */ var invertTree = function (root) { - function dfs(root) { - if (!root) return; + const dfs = root => { + if (!root) { + return; + } [root.left, root.right] = [root.right, root.left]; dfs(root.left); dfs(root.right); - } + }; dfs(root); return root; }; ``` +### **TypeScript** + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function invertTree(root: TreeNode | null): TreeNode | null { + const dfs = (root: TreeNode | null) => { + if (root === null) { + return; + } + [root.left, root.right] = [root.right, root.left]; + dfs(root.left); + dfs(root.right); + }; + dfs(root); + return root; +} +``` + ### **...** ``` diff --git a/solution/0200-0299/0226.Invert Binary Tree/Solution.cpp b/solution/0200-0299/0226.Invert Binary Tree/Solution.cpp index 02b173e8bed6a..d805b989c0d1a 100644 --- a/solution/0200-0299/0226.Invert Binary Tree/Solution.cpp +++ b/solution/0200-0299/0226.Invert Binary Tree/Solution.cpp @@ -12,16 +12,15 @@ class Solution { public: TreeNode* invertTree(TreeNode* root) { + function dfs = [&](TreeNode* root) { + if (!root) { + return; + } + swap(root->left, root->right); + dfs(root->left); + dfs(root->right); + }; dfs(root); return root; } - - void dfs(TreeNode* root) { - if (!root) return; - TreeNode* t = root->left; - root->left = root->right; - root->right = t; - dfs(root->left); - dfs(root->right); - } }; \ No newline at end of file diff --git a/solution/0200-0299/0226.Invert Binary Tree/Solution.go b/solution/0200-0299/0226.Invert Binary Tree/Solution.go index 196e5e1f716b6..05a56cde015fa 100644 --- a/solution/0200-0299/0226.Invert Binary Tree/Solution.go +++ b/solution/0200-0299/0226.Invert Binary Tree/Solution.go @@ -7,7 +7,7 @@ * } */ func invertTree(root *TreeNode) *TreeNode { - var dfs func(root *TreeNode) + var dfs func(*TreeNode) dfs = func(root *TreeNode) { if root == nil { return diff --git a/solution/0200-0299/0226.Invert Binary Tree/Solution.js b/solution/0200-0299/0226.Invert Binary Tree/Solution.js index 94e2d2edc32fa..9d24a4bfda480 100644 --- a/solution/0200-0299/0226.Invert Binary Tree/Solution.js +++ b/solution/0200-0299/0226.Invert Binary Tree/Solution.js @@ -11,12 +11,14 @@ * @return {TreeNode} */ var invertTree = function (root) { - function dfs(root) { - if (!root) return; + const dfs = root => { + if (!root) { + return; + } [root.left, root.right] = [root.right, root.left]; dfs(root.left); dfs(root.right); - } + }; dfs(root); return root; }; diff --git a/solution/0200-0299/0226.Invert Binary Tree/Solution.py b/solution/0200-0299/0226.Invert Binary Tree/Solution.py index 65300378887f3..adabf8a20411a 100644 --- a/solution/0200-0299/0226.Invert Binary Tree/Solution.py +++ b/solution/0200-0299/0226.Invert Binary Tree/Solution.py @@ -5,7 +5,7 @@ # self.left = left # self.right = right class Solution: - def invertTree(self, root: TreeNode) -> TreeNode: + def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: def dfs(root): if root is None: return diff --git a/solution/0200-0299/0226.Invert Binary Tree/Solution.ts b/solution/0200-0299/0226.Invert Binary Tree/Solution.ts new file mode 100644 index 0000000000000..72c1b6276d2f7 --- /dev/null +++ b/solution/0200-0299/0226.Invert Binary Tree/Solution.ts @@ -0,0 +1,26 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function invertTree(root: TreeNode | null): TreeNode | null { + const dfs = (root: TreeNode | null) => { + if (root === null) { + return; + } + [root.left, root.right] = [root.right, root.left]; + dfs(root.left); + dfs(root.right); + }; + dfs(root); + return root; +} diff --git a/solution/0200-0299/0250.Count Univalue Subtrees/README.md b/solution/0200-0299/0250.Count Univalue Subtrees/README.md index 85db22ea67349..a5f28b1bd9ffa 100644 --- a/solution/0200-0299/0250.Count Univalue Subtrees/README.md +++ b/solution/0200-0299/0250.Count Univalue Subtrees/README.md @@ -27,6 +27,19 @@ +**方法一:递归** + +我们设计一个递归函数 $dfs(root)$,该函数返回以 $root$ 为根的子树中所有节点的值是否相同。 + +函数 $dfs(root)$ 的递归过程如下: + +- 如果 $root$ 为空,则返回 `true`; +- 否则,我们递归地计算 $root$ 的左右子树,记为 $l$ 和 $r$;如果 $l$ 为 `false` 或者 $r$ 为 `false`,则返回 `false`;如果 $root$ 的左子树不为空且 $root$ 的左子树的值不等于 $root$ 的值,或者 $root$ 的右子树不为空且 $root$ 的右子树的值不等于 $root$ 的值,则返回 `false`;否则,我们将答案加一,并返回 `true`。 + +递归结束后,返回答案即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。 + ### **Python3** @@ -45,16 +58,16 @@ class Solution: def dfs(root): if root is None: return True - left, right = dfs(root.left), dfs(root.right) - t = True - if root.left and root.left.val != root.val: - t = False - if root.right and root.right.val != root.val: - t = False - nonlocal ans - if left and t and right: + l, r = dfs(root.left), dfs(root.right) + if not l or not r: + return False + a = root.val if root.left is None else root.left.val + b = root.val if root.right is None else root.right.val + if a == b == root.val: + nonlocal ans ans += 1 - return left and t and right + return True + return False ans = 0 dfs(root) @@ -85,7 +98,6 @@ class Solution { private int ans; public int countUnivalSubtrees(TreeNode root) { - ans = 0; dfs(root); return ans; } @@ -94,19 +106,18 @@ class Solution { if (root == null) { return true; } - boolean left = dfs(root.left); - boolean right = dfs(root.right); - boolean t = true; - if (root.left != null && root.left.val != root.val) { - t = false; - } - if (root.right != null && root.right.val != root.val) { - t = false; + boolean l = dfs(root.left); + boolean r = dfs(root.right); + if (!l || !r) { + return false; } - if (left && t && right) { + int a = root.left == null ? root.val : root.left.val; + int b = root.right == null ? root.val : root.right.val; + if (a == b && b == root.val) { ++ans; + return true; } - return left && t && right; + return false; } } ``` @@ -127,24 +138,28 @@ class Solution { */ class Solution { public: - int ans; - int countUnivalSubtrees(TreeNode* root) { - ans = 0; + int ans = 0; + function dfs = [&](TreeNode* root) -> bool { + if (!root) { + return true; + } + bool l = dfs(root->left); + bool r = dfs(root->right); + if (!l || !r) { + return false; + } + int a = root->left ? root->left->val : root->val; + int b = root->right ? root->right->val : root->val; + if (a == b && b == root->val) { + ++ans; + return true; + } + return false; + }; dfs(root); return ans; } - - bool dfs(TreeNode* root) { - if (!root) return 1; - bool left = dfs(root->left); - bool right = dfs(root->right); - bool t = 1; - if (root->left && root->left->val != root->val) t = 0; - if (root->right && root->right->val != root->val) t = 0; - if (left && t && right) ++ans; - return left && t && right; - } }; ``` @@ -159,28 +174,27 @@ public: * Right *TreeNode * } */ -func countUnivalSubtrees(root *TreeNode) int { - ans := 0 - var dfs func(root *TreeNode) bool +func countUnivalSubtrees(root *TreeNode) (ans int) { + var dfs func(*TreeNode) bool dfs = func(root *TreeNode) bool { if root == nil { return true } - left, right := dfs(root.Left), dfs(root.Right) - t := true + l, r := dfs(root.Left), dfs(root.Right) + if !l || !r { + return false + } if root.Left != nil && root.Left.Val != root.Val { - t = false + return false } if root.Right != nil && root.Right.Val != root.Val { - t = false + return false } - if left && t && right { - ans++ - } - return left && t && right + ans++ + return true } dfs(root) - return ans + return } ``` @@ -201,29 +215,71 @@ func countUnivalSubtrees(root *TreeNode) int { */ var countUnivalSubtrees = function (root) { let ans = 0; - let dfs = function (root) { + const dfs = root => { if (!root) { return true; } - const left = dfs(root.left), - right = dfs(root.right); - let t = true; - if (root.left && root.left.val != root.val) { - t = false; + const l = dfs(root.left); + const r = dfs(root.right); + if (!l || !r) { + return false; } - if (root.right && root.right.val != root.val) { - t = false; + if (root.left && root.left.val !== root.val) { + return false; } - if (left && t && right) { - ++ans; + if (root.right && root.right.val !== root.val) { + return false; } - return left && t && right; + ++ans; + return true; }; dfs(root); return ans; }; ``` +### **TypeScript** + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function countUnivalSubtrees(root: TreeNode | null): number { + let ans: number = 0; + const dfs = (root: TreeNode | null): boolean => { + if (root == null) { + return true; + } + const l: boolean = dfs(root.left); + const r: boolean = dfs(root.right); + if (!l || !r) { + return false; + } + if (root.left != null && root.left.val != root.val) { + return false; + } + if (root.right != null && root.right.val != root.val) { + return false; + } + ++ans; + return true; + }; + dfs(root); + return ans; +} +``` + ### **...** ``` diff --git a/solution/0200-0299/0250.Count Univalue Subtrees/README_EN.md b/solution/0200-0299/0250.Count Univalue Subtrees/README_EN.md index 467c3d0925a9c..33262ce052a7d 100644 --- a/solution/0200-0299/0250.Count Univalue Subtrees/README_EN.md +++ b/solution/0200-0299/0250.Count Univalue Subtrees/README_EN.md @@ -56,16 +56,16 @@ class Solution: def dfs(root): if root is None: return True - left, right = dfs(root.left), dfs(root.right) - t = True - if root.left and root.left.val != root.val: - t = False - if root.right and root.right.val != root.val: - t = False - nonlocal ans - if left and t and right: + l, r = dfs(root.left), dfs(root.right) + if not l or not r: + return False + a = root.val if root.left is None else root.left.val + b = root.val if root.right is None else root.right.val + if a == b == root.val: + nonlocal ans ans += 1 - return left and t and right + return True + return False ans = 0 dfs(root) @@ -94,7 +94,6 @@ class Solution { private int ans; public int countUnivalSubtrees(TreeNode root) { - ans = 0; dfs(root); return ans; } @@ -103,19 +102,18 @@ class Solution { if (root == null) { return true; } - boolean left = dfs(root.left); - boolean right = dfs(root.right); - boolean t = true; - if (root.left != null && root.left.val != root.val) { - t = false; - } - if (root.right != null && root.right.val != root.val) { - t = false; + boolean l = dfs(root.left); + boolean r = dfs(root.right); + if (!l || !r) { + return false; } - if (left && t && right) { + int a = root.left == null ? root.val : root.left.val; + int b = root.right == null ? root.val : root.right.val; + if (a == b && b == root.val) { ++ans; + return true; } - return left && t && right; + return false; } } ``` @@ -136,24 +134,28 @@ class Solution { */ class Solution { public: - int ans; - int countUnivalSubtrees(TreeNode* root) { - ans = 0; + int ans = 0; + function dfs = [&](TreeNode* root) -> bool { + if (!root) { + return true; + } + bool l = dfs(root->left); + bool r = dfs(root->right); + if (!l || !r) { + return false; + } + int a = root->left ? root->left->val : root->val; + int b = root->right ? root->right->val : root->val; + if (a == b && b == root->val) { + ++ans; + return true; + } + return false; + }; dfs(root); return ans; } - - bool dfs(TreeNode* root) { - if (!root) return 1; - bool left = dfs(root->left); - bool right = dfs(root->right); - bool t = 1; - if (root->left && root->left->val != root->val) t = 0; - if (root->right && root->right->val != root->val) t = 0; - if (left && t && right) ++ans; - return left && t && right; - } }; ``` @@ -168,28 +170,27 @@ public: * Right *TreeNode * } */ -func countUnivalSubtrees(root *TreeNode) int { - ans := 0 - var dfs func(root *TreeNode) bool +func countUnivalSubtrees(root *TreeNode) (ans int) { + var dfs func(*TreeNode) bool dfs = func(root *TreeNode) bool { if root == nil { return true } - left, right := dfs(root.Left), dfs(root.Right) - t := true + l, r := dfs(root.Left), dfs(root.Right) + if !l || !r { + return false + } if root.Left != nil && root.Left.Val != root.Val { - t = false + return false } if root.Right != nil && root.Right.Val != root.Val { - t = false - } - if left && t && right { - ans++ + return false } - return left && t && right + ans++ + return true } dfs(root) - return ans + return } ``` @@ -210,29 +211,71 @@ func countUnivalSubtrees(root *TreeNode) int { */ var countUnivalSubtrees = function (root) { let ans = 0; - let dfs = function (root) { + const dfs = root => { if (!root) { return true; } - const left = dfs(root.left), - right = dfs(root.right); - let t = true; - if (root.left && root.left.val != root.val) { - t = false; + const l = dfs(root.left); + const r = dfs(root.right); + if (!l || !r) { + return false; } - if (root.right && root.right.val != root.val) { - t = false; + if (root.left && root.left.val !== root.val) { + return false; } - if (left && t && right) { - ++ans; + if (root.right && root.right.val !== root.val) { + return false; } - return left && t && right; + ++ans; + return true; }; dfs(root); return ans; }; ``` +### **TypeScript** + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function countUnivalSubtrees(root: TreeNode | null): number { + let ans: number = 0; + const dfs = (root: TreeNode | null): boolean => { + if (root == null) { + return true; + } + const l: boolean = dfs(root.left); + const r: boolean = dfs(root.right); + if (!l || !r) { + return false; + } + if (root.left != null && root.left.val != root.val) { + return false; + } + if (root.right != null && root.right.val != root.val) { + return false; + } + ++ans; + return true; + }; + dfs(root); + return ans; +} +``` + ### **...** ``` diff --git a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.cpp b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.cpp index b2805fe1053de..f01f289c017d4 100644 --- a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.cpp +++ b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.cpp @@ -11,22 +11,26 @@ */ class Solution { public: - int ans; - int countUnivalSubtrees(TreeNode* root) { - ans = 0; + int ans = 0; + function dfs = [&](TreeNode* root) -> bool { + if (!root) { + return true; + } + bool l = dfs(root->left); + bool r = dfs(root->right); + if (!l || !r) { + return false; + } + int a = root->left ? root->left->val : root->val; + int b = root->right ? root->right->val : root->val; + if (a == b && b == root->val) { + ++ans; + return true; + } + return false; + }; dfs(root); return ans; } - - bool dfs(TreeNode* root) { - if (!root) return 1; - bool left = dfs(root->left); - bool right = dfs(root->right); - bool t = 1; - if (root->left && root->left->val != root->val) t = 0; - if (root->right && root->right->val != root->val) t = 0; - if (left && t && right) ++ans; - return left && t && right; - } }; \ No newline at end of file diff --git a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.go b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.go index e772089bf949e..3fbd6e828a797 100644 --- a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.go +++ b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.go @@ -6,26 +6,25 @@ * Right *TreeNode * } */ -func countUnivalSubtrees(root *TreeNode) int { - ans := 0 - var dfs func(root *TreeNode) bool +func countUnivalSubtrees(root *TreeNode) (ans int) { + var dfs func(*TreeNode) bool dfs = func(root *TreeNode) bool { if root == nil { return true } - left, right := dfs(root.Left), dfs(root.Right) - t := true + l, r := dfs(root.Left), dfs(root.Right) + if !l || !r { + return false + } if root.Left != nil && root.Left.Val != root.Val { - t = false + return false } if root.Right != nil && root.Right.Val != root.Val { - t = false - } - if left && t && right { - ans++ + return false } - return left && t && right + ans++ + return true } dfs(root) - return ans + return } \ No newline at end of file diff --git a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.java b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.java index 7fc1964a01537..db28524a1bbbb 100644 --- a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.java +++ b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.java @@ -17,7 +17,6 @@ class Solution { private int ans; public int countUnivalSubtrees(TreeNode root) { - ans = 0; dfs(root); return ans; } @@ -26,18 +25,17 @@ private boolean dfs(TreeNode root) { if (root == null) { return true; } - boolean left = dfs(root.left); - boolean right = dfs(root.right); - boolean t = true; - if (root.left != null && root.left.val != root.val) { - t = false; + boolean l = dfs(root.left); + boolean r = dfs(root.right); + if (!l || !r) { + return false; } - if (root.right != null && root.right.val != root.val) { - t = false; - } - if (left && t && right) { + int a = root.left == null ? root.val : root.left.val; + int b = root.right == null ? root.val : root.right.val; + if (a == b && b == root.val) { ++ans; + return true; } - return left && t && right; + return false; } } \ No newline at end of file diff --git a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.js b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.js index f724f2d0710ae..2c82e28570186 100644 --- a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.js +++ b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.js @@ -12,23 +12,23 @@ */ var countUnivalSubtrees = function (root) { let ans = 0; - let dfs = function (root) { + const dfs = root => { if (!root) { return true; } - const left = dfs(root.left), - right = dfs(root.right); - let t = true; - if (root.left && root.left.val != root.val) { - t = false; + const l = dfs(root.left); + const r = dfs(root.right); + if (!l || !r) { + return false; } - if (root.right && root.right.val != root.val) { - t = false; + if (root.left && root.left.val !== root.val) { + return false; } - if (left && t && right) { - ++ans; + if (root.right && root.right.val !== root.val) { + return false; } - return left && t && right; + ++ans; + return true; }; dfs(root); return ans; diff --git a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.py b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.py index bddec520e87e2..1fe896b34c501 100644 --- a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.py +++ b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.py @@ -9,16 +9,16 @@ def countUnivalSubtrees(self, root: Optional[TreeNode]) -> int: def dfs(root): if root is None: return True - left, right = dfs(root.left), dfs(root.right) - t = True - if root.left and root.left.val != root.val: - t = False - if root.right and root.right.val != root.val: - t = False - nonlocal ans - if left and t and right: + l, r = dfs(root.left), dfs(root.right) + if not l or not r: + return False + a = root.val if root.left is None else root.left.val + b = root.val if root.right is None else root.right.val + if a == b == root.val: + nonlocal ans ans += 1 - return left and t and right + return True + return False ans = 0 dfs(root) diff --git a/solution/0200-0299/0250.Count Univalue Subtrees/Solution.ts b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.ts new file mode 100644 index 0000000000000..52ba9d1c28f08 --- /dev/null +++ b/solution/0200-0299/0250.Count Univalue Subtrees/Solution.ts @@ -0,0 +1,37 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function countUnivalSubtrees(root: TreeNode | null): number { + let ans: number = 0; + const dfs = (root: TreeNode | null): boolean => { + if (root == null) { + return true; + } + const l: boolean = dfs(root.left); + const r: boolean = dfs(root.right); + if (!l || !r) { + return false; + } + if (root.left != null && root.left.val != root.val) { + return false; + } + if (root.right != null && root.right.val != root.val) { + return false; + } + ++ans; + return true; + }; + dfs(root); + return ans; +} diff --git a/solution/0200-0299/0251.Flatten 2D Vector/README.md b/solution/0200-0299/0251.Flatten 2D Vector/README.md index 1d09019eaba51..82ed1a60ee6b5 100644 --- a/solution/0200-0299/0251.Flatten 2D Vector/README.md +++ b/solution/0200-0299/0251.Flatten 2D Vector/README.md @@ -41,6 +41,18 @@ iterator.hasNext(); // 返回 false +**方法一:双指针** + +我们定义两个指针 $i$ 和 $j$,分别指向当前二维向量的行和列,初始时 $i = 0$,$j = 0$。 + +接下来,我们设计一个函数 $forward()$,用于将 $i$ 和 $j$ 向后移动,直到指向一个非空的元素。 + +每次调用 `next` 方法时,我们先调用 $forward()$,然后返回当前指向的元素,最后将 $j$ 向后移动一位。 + +每次调用 `hasNext` 方法时,我们先调用 $forward()$,然后判断 $i$ 是否小于二维向量的行数,如果是,则返回 `true`,否则返回 `false`。 + +时间复杂度 $O(1)$,空间复杂度 $O(1)$。 + ### **Python3** @@ -50,18 +62,24 @@ iterator.hasNext(); // 返回 false ```python class Vector2D: def __init__(self, vec: List[List[int]]): - self.flatten = [] - for item in vec: - for e in item: - self.flatten.append(e) - self.cur = -1 + self.i = 0 + self.j = 0 + self.vec = vec def next(self) -> int: - self.cur += 1 - return self.flatten[self.cur] + self.forward() + ans = self.vec[self.i][self.j] + self.j += 1 + return ans def hasNext(self) -> bool: - return self.cur < len(self.flatten) - 1 + self.forward() + return self.i < len(self.vec) + + def forward(self): + while self.i < len(self.vec) and self.j >= len(self.vec[self.i]): + self.i += 1 + self.j = 0 # Your Vector2D object will be instantiated and called as such: @@ -75,7 +93,158 @@ class Vector2D: ```java +class Vector2D { + private int i; + private int j; + private int[][] vec; + + public Vector2D(int[][] vec) { + this.vec = vec; + } + + public int next() { + forward(); + return vec[i][j++]; + } + + public boolean hasNext() { + forward(); + return i < vec.length; + } + + private void forward() { + while (i < vec.length && j >= vec[i].length) { + ++i; + j = 0; + } + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D obj = new Vector2D(vec); + * int param_1 = obj.next(); + * boolean param_2 = obj.hasNext(); + */ +``` + +### **C++** + +```cpp +class Vector2D { +public: + Vector2D(vector>& vec) { + this->vec = move(vec); + } + + int next() { + forward(); + return vec[i][j++]; + } + + bool hasNext() { + forward(); + return i < vec.size(); + } + +private: + int i = 0; + int j = 0; + vector> vec; + + void forward() { + while (i < vec.size() && j >= vec[i].size()) { + ++i; + j = 0; + } + } +}; + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D* obj = new Vector2D(vec); + * int param_1 = obj->next(); + * bool param_2 = obj->hasNext(); + */ +``` + +### **Go** + +```go +type Vector2D struct { + i, j int + vec [][]int +} + +func Constructor(vec [][]int) Vector2D { + return Vector2D{vec: vec} +} + +func (this *Vector2D) Next() int { + this.forward() + ans := this.vec[this.i][this.j] + this.j++ + return ans +} + +func (this *Vector2D) HasNext() bool { + this.forward() + return this.i < len(this.vec) +} + +func (this *Vector2D) forward() { + for this.i < len(this.vec) && this.j >= len(this.vec[this.i]) { + this.i++ + this.j = 0 + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * obj := Constructor(vec); + * param_1 := obj.Next(); + * param_2 := obj.HasNext(); + */ +``` + +### **TypeScript** + +```ts +class Vector2D { + i: number; + j: number; + vec: number[][]; + + constructor(vec: number[][]) { + this.i = 0; + this.j = 0; + this.vec = vec; + } + + next(): number { + this.forward(); + return this.vec[this.i][this.j++]; + } + + hasNext(): boolean { + this.forward(); + return this.i < this.vec.length; + } + + forward(): void { + while (this.i < this.vec.length && this.j >= this.vec[this.i].length) { + ++this.i; + this.j = 0; + } + } +} +/** + * Your Vector2D object will be instantiated and called as such: + * var obj = new Vector2D(vec) + * var param_1 = obj.next() + * var param_2 = obj.hasNext() + */ ``` ### **...** diff --git a/solution/0200-0299/0251.Flatten 2D Vector/README_EN.md b/solution/0200-0299/0251.Flatten 2D Vector/README_EN.md index efdc521ebfb36..18e8011f6e44d 100644 --- a/solution/0200-0299/0251.Flatten 2D Vector/README_EN.md +++ b/solution/0200-0299/0251.Flatten 2D Vector/README_EN.md @@ -57,18 +57,24 @@ vector2D.hasNext(); // return False ```python class Vector2D: def __init__(self, vec: List[List[int]]): - self.flatten = [] - for item in vec: - for e in item: - self.flatten.append(e) - self.cur = -1 + self.i = 0 + self.j = 0 + self.vec = vec def next(self) -> int: - self.cur += 1 - return self.flatten[self.cur] + self.forward() + ans = self.vec[self.i][self.j] + self.j += 1 + return ans def hasNext(self) -> bool: - return self.cur < len(self.flatten) - 1 + self.forward() + return self.i < len(self.vec) + + def forward(self): + while self.i < len(self.vec) and self.j >= len(self.vec[self.i]): + self.i += 1 + self.j = 0 # Your Vector2D object will be instantiated and called as such: @@ -80,7 +86,158 @@ class Vector2D: ### **Java** ```java +class Vector2D { + private int i; + private int j; + private int[][] vec; + + public Vector2D(int[][] vec) { + this.vec = vec; + } + + public int next() { + forward(); + return vec[i][j++]; + } + + public boolean hasNext() { + forward(); + return i < vec.length; + } + + private void forward() { + while (i < vec.length && j >= vec[i].length) { + ++i; + j = 0; + } + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D obj = new Vector2D(vec); + * int param_1 = obj.next(); + * boolean param_2 = obj.hasNext(); + */ +``` + +### **C++** + +```cpp +class Vector2D { +public: + Vector2D(vector>& vec) { + this->vec = move(vec); + } + + int next() { + forward(); + return vec[i][j++]; + } + + bool hasNext() { + forward(); + return i < vec.size(); + } + +private: + int i = 0; + int j = 0; + vector> vec; + + void forward() { + while (i < vec.size() && j >= vec[i].size()) { + ++i; + j = 0; + } + } +}; + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D* obj = new Vector2D(vec); + * int param_1 = obj->next(); + * bool param_2 = obj->hasNext(); + */ +``` + +### **Go** + +```go +type Vector2D struct { + i, j int + vec [][]int +} + +func Constructor(vec [][]int) Vector2D { + return Vector2D{vec: vec} +} + +func (this *Vector2D) Next() int { + this.forward() + ans := this.vec[this.i][this.j] + this.j++ + return ans +} + +func (this *Vector2D) HasNext() bool { + this.forward() + return this.i < len(this.vec) +} + +func (this *Vector2D) forward() { + for this.i < len(this.vec) && this.j >= len(this.vec[this.i]) { + this.i++ + this.j = 0 + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * obj := Constructor(vec); + * param_1 := obj.Next(); + * param_2 := obj.HasNext(); + */ +``` +### **TypeScript** + +```ts +class Vector2D { + i: number; + j: number; + vec: number[][]; + + constructor(vec: number[][]) { + this.i = 0; + this.j = 0; + this.vec = vec; + } + + next(): number { + this.forward(); + return this.vec[this.i][this.j++]; + } + + hasNext(): boolean { + this.forward(); + return this.i < this.vec.length; + } + + forward(): void { + while (this.i < this.vec.length && this.j >= this.vec[this.i].length) { + ++this.i; + this.j = 0; + } + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * var obj = new Vector2D(vec) + * var param_1 = obj.next() + * var param_2 = obj.hasNext() + */ ``` ### **...** diff --git a/solution/0200-0299/0251.Flatten 2D Vector/Solution.cpp b/solution/0200-0299/0251.Flatten 2D Vector/Solution.cpp new file mode 100644 index 0000000000000..d26f0db249185 --- /dev/null +++ b/solution/0200-0299/0251.Flatten 2D Vector/Solution.cpp @@ -0,0 +1,35 @@ +class Vector2D { +public: + Vector2D(vector>& vec) { + this->vec = move(vec); + } + + int next() { + forward(); + return vec[i][j++]; + } + + bool hasNext() { + forward(); + return i < vec.size(); + } + +private: + int i = 0; + int j = 0; + vector> vec; + + void forward() { + while (i < vec.size() && j >= vec[i].size()) { + ++i; + j = 0; + } + } +}; + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D* obj = new Vector2D(vec); + * int param_1 = obj->next(); + * bool param_2 = obj->hasNext(); + */ \ No newline at end of file diff --git a/solution/0200-0299/0251.Flatten 2D Vector/Solution.go b/solution/0200-0299/0251.Flatten 2D Vector/Solution.go new file mode 100644 index 0000000000000..e6e77b45c80e8 --- /dev/null +++ b/solution/0200-0299/0251.Flatten 2D Vector/Solution.go @@ -0,0 +1,34 @@ +type Vector2D struct { + i, j int + vec [][]int +} + +func Constructor(vec [][]int) Vector2D { + return Vector2D{vec: vec} +} + +func (this *Vector2D) Next() int { + this.forward() + ans := this.vec[this.i][this.j] + this.j++ + return ans +} + +func (this *Vector2D) HasNext() bool { + this.forward() + return this.i < len(this.vec) +} + +func (this *Vector2D) forward() { + for this.i < len(this.vec) && this.j >= len(this.vec[this.i]) { + this.i++ + this.j = 0 + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * obj := Constructor(vec); + * param_1 := obj.Next(); + * param_2 := obj.HasNext(); + */ \ No newline at end of file diff --git a/solution/0200-0299/0251.Flatten 2D Vector/Solution.java b/solution/0200-0299/0251.Flatten 2D Vector/Solution.java index e69de29bb2d1d..ac08029cf7ee3 100644 --- a/solution/0200-0299/0251.Flatten 2D Vector/Solution.java +++ b/solution/0200-0299/0251.Flatten 2D Vector/Solution.java @@ -0,0 +1,33 @@ +class Vector2D { + private int i; + private int j; + private int[][] vec; + + public Vector2D(int[][] vec) { + this.vec = vec; + } + + public int next() { + forward(); + return vec[i][j++]; + } + + public boolean hasNext() { + forward(); + return i < vec.length; + } + + private void forward() { + while (i < vec.length && j >= vec[i].length) { + ++i; + j = 0; + } + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D obj = new Vector2D(vec); + * int param_1 = obj.next(); + * boolean param_2 = obj.hasNext(); + */ \ No newline at end of file diff --git a/solution/0200-0299/0251.Flatten 2D Vector/Solution.py b/solution/0200-0299/0251.Flatten 2D Vector/Solution.py index d7dbf7ff48803..3123c94102e1b 100644 --- a/solution/0200-0299/0251.Flatten 2D Vector/Solution.py +++ b/solution/0200-0299/0251.Flatten 2D Vector/Solution.py @@ -1,17 +1,23 @@ class Vector2D: def __init__(self, vec: List[List[int]]): - self.flatten = [] - for item in vec: - for e in item: - self.flatten.append(e) - self.cur = -1 + self.i = 0 + self.j = 0 + self.vec = vec def next(self) -> int: - self.cur += 1 - return self.flatten[self.cur] + self.forward() + ans = self.vec[self.i][self.j] + self.j += 1 + return ans def hasNext(self) -> bool: - return self.cur < len(self.flatten) - 1 + self.forward() + return self.i < len(self.vec) + + def forward(self): + while self.i < len(self.vec) and self.j >= len(self.vec[self.i]): + self.i += 1 + self.j = 0 # Your Vector2D object will be instantiated and called as such: diff --git a/solution/0200-0299/0251.Flatten 2D Vector/Solution.ts b/solution/0200-0299/0251.Flatten 2D Vector/Solution.ts new file mode 100644 index 0000000000000..d5a98e01bf404 --- /dev/null +++ b/solution/0200-0299/0251.Flatten 2D Vector/Solution.ts @@ -0,0 +1,35 @@ +class Vector2D { + i: number; + j: number; + vec: number[][]; + + constructor(vec: number[][]) { + this.i = 0; + this.j = 0; + this.vec = vec; + } + + next(): number { + this.forward(); + return this.vec[this.i][this.j++]; + } + + hasNext(): boolean { + this.forward(); + return this.i < this.vec.length; + } + + forward(): void { + while (this.i < this.vec.length && this.j >= this.vec[this.i].length) { + ++this.i; + this.j = 0; + } + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * var obj = new Vector2D(vec) + * var param_1 = obj.next() + * var param_2 = obj.hasNext() + */ diff --git a/solution/0200-0299/0252.Meeting Rooms/README.md b/solution/0200-0299/0252.Meeting Rooms/README.md index 912c7f3cca3df..8dac7ee15df00 100644 --- a/solution/0200-0299/0252.Meeting Rooms/README.md +++ b/solution/0200-0299/0252.Meeting Rooms/README.md @@ -38,6 +38,14 @@ +**方法一:排序** + +我们将会议按照开始时间进行排序,然后遍历排序后的会议,如果当前会议的开始时间小于前一个会议的结束时间,则说明两个会议有重叠,返回 `false` 即可。 + +遍历结束后,返回 `true`。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为会议数量。 + ### **Python3** @@ -47,11 +55,8 @@ ```python class Solution: def canAttendMeetings(self, intervals: List[List[int]]) -> bool: - intervals.sort(key=lambda x: x[0]) - for i in range(len(intervals) - 1): - if intervals[i][1] > intervals[i + 1][0]: - return False - return True + intervals.sort() + return all(a[1] <= b[0] for a, b in pairwise(intervals)) ``` ### **Java** @@ -61,12 +66,65 @@ class Solution: ```java class Solution { public boolean canAttendMeetings(int[][] intervals) { - Arrays.sort(intervals, Comparator.comparingInt(a -> a[0])); - for (int i = 0, n = intervals.length; i < n - 1; ++i) { - if (intervals[i][1] > intervals[i + 1][0]) return false; + Arrays.sort(intervals, (a, b) -> a[0] - b[0]); + for (int i = 1; i < intervals.length; ++i) { + var a = intervals[i - 1]; + var b = intervals[i]; + if (a[1] > b[0]) { + return false; + } + } + return true; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + bool canAttendMeetings(vector>& intervals) { + sort(intervals.begin(), intervals.end(), [](const vector& a, const vector& b) { + return a[0] < b[0]; + }); + for (int i = 1; i < intervals.size(); ++i) { + if (intervals[i][0] < intervals[i - 1][1]) { + return false; + } } return true; } +}; +``` + +### **Go** + +```go +func canAttendMeetings(intervals [][]int) bool { + sort.Slice(intervals, func(i, j int) bool { + return intervals[i][0] < intervals[j][0] + }) + for i := 1; i < len(intervals); i++ { + if intervals[i][0] < intervals[i-1][1] { + return false + } + } + return true +} +``` + +### **TypeScript** + +```ts +function canAttendMeetings(intervals: number[][]): boolean { + intervals.sort((a, b) => a[0] - b[0]); + for (let i = 1; i < intervals.length; ++i) { + if (intervals[i][0] < intervals[i - 1][1]) { + return false; + } + } + return true; } ``` diff --git a/solution/0200-0299/0252.Meeting Rooms/README_EN.md b/solution/0200-0299/0252.Meeting Rooms/README_EN.md index 27ecb5dfdc382..7d80b8695966b 100644 --- a/solution/0200-0299/0252.Meeting Rooms/README_EN.md +++ b/solution/0200-0299/0252.Meeting Rooms/README_EN.md @@ -32,11 +32,8 @@ ```python class Solution: def canAttendMeetings(self, intervals: List[List[int]]) -> bool: - intervals.sort(key=lambda x: x[0]) - for i in range(len(intervals) - 1): - if intervals[i][1] > intervals[i + 1][0]: - return False - return True + intervals.sort() + return all(a[1] <= b[0] for a, b in pairwise(intervals)) ``` ### **Java** @@ -44,15 +41,68 @@ class Solution: ```java class Solution { public boolean canAttendMeetings(int[][] intervals) { - Arrays.sort(intervals, Comparator.comparingInt(a -> a[0])); - for (int i = 0, n = intervals.length; i < n - 1; ++i) { - if (intervals[i][1] > intervals[i + 1][0]) return false; + Arrays.sort(intervals, (a, b) -> a[0] - b[0]); + for (int i = 1; i < intervals.length; ++i) { + var a = intervals[i - 1]; + var b = intervals[i]; + if (a[1] > b[0]) { + return false; + } } return true; } } ``` +### **C++** + +```cpp +class Solution { +public: + bool canAttendMeetings(vector>& intervals) { + sort(intervals.begin(), intervals.end(), [](const vector& a, const vector& b) { + return a[0] < b[0]; + }); + for (int i = 1; i < intervals.size(); ++i) { + if (intervals[i][0] < intervals[i - 1][1]) { + return false; + } + } + return true; + } +}; +``` + +### **Go** + +```go +func canAttendMeetings(intervals [][]int) bool { + sort.Slice(intervals, func(i, j int) bool { + return intervals[i][0] < intervals[j][0] + }) + for i := 1; i < len(intervals); i++ { + if intervals[i][0] < intervals[i-1][1] { + return false + } + } + return true +} +``` + +### **TypeScript** + +```ts +function canAttendMeetings(intervals: number[][]): boolean { + intervals.sort((a, b) => a[0] - b[0]); + for (let i = 1; i < intervals.length; ++i) { + if (intervals[i][0] < intervals[i - 1][1]) { + return false; + } + } + return true; +} +``` + ### **...** ``` diff --git a/solution/0200-0299/0252.Meeting Rooms/Solution.cpp b/solution/0200-0299/0252.Meeting Rooms/Solution.cpp new file mode 100644 index 0000000000000..7e6b6657fe2e5 --- /dev/null +++ b/solution/0200-0299/0252.Meeting Rooms/Solution.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + bool canAttendMeetings(vector>& intervals) { + sort(intervals.begin(), intervals.end(), [](const vector& a, const vector& b) { + return a[0] < b[0]; + }); + for (int i = 1; i < intervals.size(); ++i) { + if (intervals[i][0] < intervals[i - 1][1]) { + return false; + } + } + return true; + } +}; \ No newline at end of file diff --git a/solution/0200-0299/0252.Meeting Rooms/Solution.go b/solution/0200-0299/0252.Meeting Rooms/Solution.go new file mode 100644 index 0000000000000..2ff9d28baf828 --- /dev/null +++ b/solution/0200-0299/0252.Meeting Rooms/Solution.go @@ -0,0 +1,11 @@ +func canAttendMeetings(intervals [][]int) bool { + sort.Slice(intervals, func(i, j int) bool { + return intervals[i][0] < intervals[j][0] + }) + for i := 1; i < len(intervals); i++ { + if intervals[i][0] < intervals[i-1][1] { + return false + } + } + return true +} \ No newline at end of file diff --git a/solution/0200-0299/0252.Meeting Rooms/Solution.java b/solution/0200-0299/0252.Meeting Rooms/Solution.java index 0d66c4d418406..565b05b05f2f8 100644 --- a/solution/0200-0299/0252.Meeting Rooms/Solution.java +++ b/solution/0200-0299/0252.Meeting Rooms/Solution.java @@ -1,8 +1,12 @@ class Solution { public boolean canAttendMeetings(int[][] intervals) { - Arrays.sort(intervals, Comparator.comparingInt(a -> a[0])); - for (int i = 0, n = intervals.length; i < n - 1; ++i) { - if (intervals[i][1] > intervals[i + 1][0]) return false; + Arrays.sort(intervals, (a, b) -> a[0] - b[0]); + for (int i = 1; i < intervals.length; ++i) { + var a = intervals[i - 1]; + var b = intervals[i]; + if (a[1] > b[0]) { + return false; + } } return true; } diff --git a/solution/0200-0299/0252.Meeting Rooms/Solution.py b/solution/0200-0299/0252.Meeting Rooms/Solution.py index fca30d7718a64..e55fdbb373ea0 100644 --- a/solution/0200-0299/0252.Meeting Rooms/Solution.py +++ b/solution/0200-0299/0252.Meeting Rooms/Solution.py @@ -1,7 +1,4 @@ class Solution: def canAttendMeetings(self, intervals: List[List[int]]) -> bool: - intervals.sort(key=lambda x: x[0]) - for i in range(len(intervals) - 1): - if intervals[i][1] > intervals[i + 1][0]: - return False - return True + intervals.sort() + return all(a[1] <= b[0] for a, b in pairwise(intervals)) diff --git a/solution/0200-0299/0252.Meeting Rooms/Solution.ts b/solution/0200-0299/0252.Meeting Rooms/Solution.ts new file mode 100644 index 0000000000000..d08aead6c81ed --- /dev/null +++ b/solution/0200-0299/0252.Meeting Rooms/Solution.ts @@ -0,0 +1,9 @@ +function canAttendMeetings(intervals: number[][]): boolean { + intervals.sort((a, b) => a[0] - b[0]); + for (let i = 1; i < intervals.length; ++i) { + if (intervals[i][0] < intervals[i - 1][1]) { + return false; + } + } + return true; +} diff --git a/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/README.md b/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/README.md index 52075a8de797f..635d8b61d8cf8 100644 --- a/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/README.md +++ b/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/README.md @@ -251,6 +251,24 @@ func countWays(ranges [][]int) int { } ``` +### **TypeScript** + +```ts +function countWays(ranges: number[][]): number { + ranges.sort((a, b) => a[0] - b[0]); + let mx = -1; + let ans = 1; + const mod = 10 ** 9 + 7; + for (const [start, end] of ranges) { + if (start > mx) { + ans = (ans * 2) % mod; + } + mx = Math.max(mx, end); + } + return ans; +} +``` + ### **...** ``` diff --git a/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/README_EN.md b/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/README_EN.md index 21ed31bc21a3a..13068dc4ae36f 100644 --- a/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/README_EN.md +++ b/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/README_EN.md @@ -233,6 +233,24 @@ func countWays(ranges [][]int) int { } ``` +### **TypeScript** + +```ts +function countWays(ranges: number[][]): number { + ranges.sort((a, b) => a[0] - b[0]); + let mx = -1; + let ans = 1; + const mod = 10 ** 9 + 7; + for (const [start, end] of ranges) { + if (start > mx) { + ans = (ans * 2) % mod; + } + mx = Math.max(mx, end); + } + return ans; +} +``` + ### **...** ``` diff --git a/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/Solution.ts b/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/Solution.ts new file mode 100644 index 0000000000000..92e8aea8e6277 --- /dev/null +++ b/solution/2500-2599/2580.Count Ways to Group Overlapping Ranges/Solution.ts @@ -0,0 +1,13 @@ +function countWays(ranges: number[][]): number { + ranges.sort((a, b) => a[0] - b[0]); + let mx = -1; + let ans = 1; + const mod = 10 ** 9 + 7; + for (const [start, end] of ranges) { + if (start > mx) { + ans = (ans * 2) % mod; + } + mx = Math.max(mx, end); + } + return ans; +} diff --git a/solution/2500-2599/2585.Number of Ways to Earn Points/README.md b/solution/2500-2599/2585.Number of Ways to Earn Points/README.md index 5548488af787f..0a9bd0d3350be 100644 --- a/solution/2500-2599/2585.Number of Ways to Earn Points/README.md +++ b/solution/2500-2599/2585.Number of Ways to Earn Points/README.md @@ -181,6 +181,28 @@ func waysToReachTarget(target int, types [][]int) int { } ``` +### **TypeScript** + +```ts +function waysToReachTarget(target: number, types: number[][]): number { + const n = types.length; + const mod = 10 ** 9 + 7; + const f: number[][] = Array.from({ length: n + 1 }, () => Array(target + 1).fill(0)); + f[0][0] = 1; + for (let i = 1; i <= n; ++i) { + const [count, marks] = types[i - 1]; + for (let j = 0; j <= target; ++j) { + for (let k = 0; k <= count; ++k) { + if (j >= k * marks) { + f[i][j] = (f[i][j] + f[i - 1][j - k * marks]) % mod; + } + } + } + } + return f[n][target]; +}; +``` + ### **...** ``` diff --git a/solution/2500-2599/2585.Number of Ways to Earn Points/README_EN.md b/solution/2500-2599/2585.Number of Ways to Earn Points/README_EN.md index 087ed24054e12..7dc7b60f144e6 100644 --- a/solution/2500-2599/2585.Number of Ways to Earn Points/README_EN.md +++ b/solution/2500-2599/2585.Number of Ways to Earn Points/README_EN.md @@ -161,6 +161,28 @@ func waysToReachTarget(target int, types [][]int) int { } ``` +### **TypeScript** + +```ts +function waysToReachTarget(target: number, types: number[][]): number { + const n = types.length; + const mod = 10 ** 9 + 7; + const f: number[][] = Array.from({ length: n + 1 }, () => Array(target + 1).fill(0)); + f[0][0] = 1; + for (let i = 1; i <= n; ++i) { + const [count, marks] = types[i - 1]; + for (let j = 0; j <= target; ++j) { + for (let k = 0; k <= count; ++k) { + if (j >= k * marks) { + f[i][j] = (f[i][j] + f[i - 1][j - k * marks]) % mod; + } + } + } + } + return f[n][target]; +}; +``` + ### **...** ``` diff --git a/solution/2500-2599/2585.Number of Ways to Earn Points/Solution.ts b/solution/2500-2599/2585.Number of Ways to Earn Points/Solution.ts new file mode 100644 index 0000000000000..9995976910e07 --- /dev/null +++ b/solution/2500-2599/2585.Number of Ways to Earn Points/Solution.ts @@ -0,0 +1,17 @@ +function waysToReachTarget(target: number, types: number[][]): number { + const n = types.length; + const mod = 10 ** 9 + 7; + const f: number[][] = Array.from({ length: n + 1 }, () => Array(target + 1).fill(0)); + f[0][0] = 1; + for (let i = 1; i <= n; ++i) { + const [count, marks] = types[i - 1]; + for (let j = 0; j <= target; ++j) { + for (let k = 0; k <= count; ++k) { + if (j >= k * marks) { + f[i][j] = (f[i][j] + f[i - 1][j - k * marks]) % mod; + } + } + } + } + return f[n][target]; +}; \ No newline at end of file diff --git a/solution/CONTEST_README.md b/solution/CONTEST_README.md index 461e14587c681..aa63ef110443c 100644 --- a/solution/CONTEST_README.md +++ b/solution/CONTEST_README.md @@ -11,8 +11,8 @@ | 段位 | 比例 | 段位名 | 国服分数线 | 勋章 | | ----- | ------ | -------- | --------- | --------------------------------------------------------------------------- | -| LV3 | 5% | Guardian | ≥2265.64 |

| -| LV2 | 20% | Knight | ≥1894.28 |

| +| LV3 | 5% | Guardian | ≥2251.88 |

| +| LV2 | 20% | Knight | ≥1879.80 |

| | LV1 | 75% | - | - | - | 力扣竞赛 **全国排名前 10** 的用户,全站用户名展示为品牌橙色。 diff --git a/solution/contest.py b/solution/contest.py index e619d3b2da151..fd9b9874c48ff 100644 --- a/solution/contest.py +++ b/solution/contest.py @@ -127,8 +127,8 @@ def generate_contest_list(): | 段位 | 比例 | 段位名 | 国服分数线 | 勋章 | | ----- | ------ | -------- | --------- | --------------------------------------------------------------------------- | -| LV3 | 5% | Guardian | ≥2265.64 |

| -| LV2 | 20% | Knight | ≥1894.28 |

| +| LV3 | 5% | Guardian | ≥2251.88 |

| +| LV2 | 20% | Knight | ≥1879.80 |

| | LV1 | 75% | - | - | - | 力扣竞赛 **全国排名前 10** 的用户,全站用户名展示为品牌橙色。 diff --git a/solution/rating.py b/solution/rating.py index 791f889e62f5c..c2be9eead0e68 100644 --- a/solution/rating.py +++ b/solution/rating.py @@ -104,7 +104,7 @@ def get_user_ranking(self, uid): return None def get_1600_count(self): - left, right = 1, 1000 if self.region == 'CN' else 3000 + left, right = 1, 4000 while left < right: mid = (left + right + 1) >> 1 page = self.load_page(mid) @@ -116,17 +116,17 @@ def get_1600_count(self): left = mid else: right = mid - 1 - page = self.load_page(left) + page = [uid for _, uid in self.load_page(left) if uid] print('校准中...') left, right = 0, len(page) - 1 while left < right: mid = (left + right + 1) >> 1 - ranking, score = self.get_user_ranking(page[mid][1]) + ranking, score = self.get_user_ranking(page[mid]) if score >= 1600: left = mid else: right = mid - 1 - return self.get_user_ranking(page[left][1])[0] + return self.get_user_ranking(page[left])[0] def get_user(self, rank): p = (rank - 1) // 25 + 1