diff --git a/solution/0000-0099/0052.N-Queens II/README.md b/solution/0000-0099/0052.N-Queens II/README.md index e5cc7fea18fd7..ab98daff541a4 100644 --- a/solution/0000-0099/0052.N-Queens II/README.md +++ b/solution/0000-0099/0052.N-Queens II/README.md @@ -66,7 +66,7 @@ ```python class Solution: def totalNQueens(self, n: int) -> int: - def dfs(i): + def dfs(i: int): if i == n: nonlocal ans ans += 1 @@ -184,6 +184,34 @@ func totalNQueens(n int) (ans int) { } ``` +### **TypeScript** + +```ts +function totalNQueens(n: number): number { + const cols: boolean[] = Array(10).fill(false); + const dg: boolean[] = Array(20).fill(false); + const udg: boolean[] = Array(20).fill(false); + let ans = 0; + const dfs = (i: number) => { + if (i === n) { + ++ans; + return; + } + for (let j = 0; j < n; ++j) { + let [a, b] = [i + j, i - j + n]; + if (cols[j] || dg[a] || udg[b]) { + continue; + } + cols[j] = dg[a] = udg[b] = true; + dfs(i + 1); + cols[j] = dg[a] = udg[b] = false; + } + }; + dfs(0); + return ans; +} +``` + ### **...** ``` diff --git a/solution/0000-0099/0052.N-Queens II/README_EN.md b/solution/0000-0099/0052.N-Queens II/README_EN.md index fe69a8aedc0eb..2e2dcf09f72a1 100644 --- a/solution/0000-0099/0052.N-Queens II/README_EN.md +++ b/solution/0000-0099/0052.N-Queens II/README_EN.md @@ -54,7 +54,7 @@ The time complexity is $O(n!)$, and the space complexity is $O(n)$. Here, $n$ is ```python class Solution: def totalNQueens(self, n: int) -> int: - def dfs(i): + def dfs(i: int): if i == n: nonlocal ans ans += 1 @@ -170,6 +170,34 @@ func totalNQueens(n int) (ans int) { } ``` +### **TypeScript** + +```ts +function totalNQueens(n: number): number { + const cols: boolean[] = Array(10).fill(false); + const dg: boolean[] = Array(20).fill(false); + const udg: boolean[] = Array(20).fill(false); + let ans = 0; + const dfs = (i: number) => { + if (i === n) { + ++ans; + return; + } + for (let j = 0; j < n; ++j) { + let [a, b] = [i + j, i - j + n]; + if (cols[j] || dg[a] || udg[b]) { + continue; + } + cols[j] = dg[a] = udg[b] = true; + dfs(i + 1); + cols[j] = dg[a] = udg[b] = false; + } + }; + dfs(0); + return ans; +} +``` + ### **...** ``` diff --git a/solution/0000-0099/0052.N-Queens II/Solution.py b/solution/0000-0099/0052.N-Queens II/Solution.py index e3ec94523ced1..5609f42862b92 100644 --- a/solution/0000-0099/0052.N-Queens II/Solution.py +++ b/solution/0000-0099/0052.N-Queens II/Solution.py @@ -1,21 +1,21 @@ -class Solution: - def totalNQueens(self, n: int) -> int: - def dfs(i): - if i == n: - nonlocal ans - ans += 1 - return - for j in range(n): - a, b = i + j, i - j + n - if cols[j] or dg[a] or udg[b]: - continue - cols[j] = dg[a] = udg[b] = True - dfs(i + 1) - cols[j] = dg[a] = udg[b] = False - - cols = [False] * 10 - dg = [False] * 20 - udg = [False] * 20 - ans = 0 - dfs(0) - return ans +class Solution: + def totalNQueens(self, n: int) -> int: + def dfs(i: int): + if i == n: + nonlocal ans + ans += 1 + return + for j in range(n): + a, b = i + j, i - j + n + if cols[j] or dg[a] or udg[b]: + continue + cols[j] = dg[a] = udg[b] = True + dfs(i + 1) + cols[j] = dg[a] = udg[b] = False + + cols = [False] * 10 + dg = [False] * 20 + udg = [False] * 20 + ans = 0 + dfs(0) + return ans diff --git a/solution/0000-0099/0052.N-Queens II/Solution.ts b/solution/0000-0099/0052.N-Queens II/Solution.ts new file mode 100644 index 0000000000000..c252daffbec66 --- /dev/null +++ b/solution/0000-0099/0052.N-Queens II/Solution.ts @@ -0,0 +1,23 @@ +function totalNQueens(n: number): number { + const cols: boolean[] = Array(10).fill(false); + const dg: boolean[] = Array(20).fill(false); + const udg: boolean[] = Array(20).fill(false); + let ans = 0; + const dfs = (i: number) => { + if (i === n) { + ++ans; + return; + } + for (let j = 0; j < n; ++j) { + let [a, b] = [i + j, i - j + n]; + if (cols[j] || dg[a] || udg[b]) { + continue; + } + cols[j] = dg[a] = udg[b] = true; + dfs(i + 1); + cols[j] = dg[a] = udg[b] = false; + } + }; + dfs(0); + return ans; +} diff --git a/solution/0000-0099/0063.Unique Paths II/README.md b/solution/0000-0099/0063.Unique Paths II/README.md index 33e879199e4ef..ca09b0d53109c 100644 --- a/solution/0000-0099/0063.Unique Paths II/README.md +++ b/solution/0000-0099/0063.Unique Paths II/README.md @@ -55,7 +55,7 @@ 首先初始化 $dp$ 第一列和第一行的所有值,然后遍历其它行和列,有两种情况: -- 若 $obstacleGrid[i][j] = 1$,说明路径数为 $0$,那么 $dp[i][j] = 0 ¥; +- 若 $obstacleGrid[i][j] = 1$,说明路径数为 $0$,那么 $dp[i][j] = 0$; - 若 ¥ obstacleGrid[i][j] = 0$,则 $dp[i][j] = dp[i - 1][j] + dp[i][j - 1]$。 最后返回 $dp[m - 1][n - 1]$ 即可。 diff --git a/solution/0000-0099/0065.Valid Number/README.md b/solution/0000-0099/0065.Valid Number/README.md index 1b0b9a108516e..fddc5bbaa130d 100644 --- a/solution/0000-0099/0065.Valid Number/README.md +++ b/solution/0000-0099/0065.Valid Number/README.md @@ -91,7 +91,7 @@ 遍历完字符串后,返回 `true`。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为字符串长度。 +时间复杂度 $O(n)$,其中 $n$ 为字符串长度。空间复杂度 $O(1)$。 diff --git a/solution/0000-0099/0069.Sqrt(x)/README.md b/solution/0000-0099/0069.Sqrt(x)/README.md index 61b466ca3a94b..2accad08078dd 100644 --- a/solution/0000-0099/0069.Sqrt(x)/README.md +++ b/solution/0000-0099/0069.Sqrt(x)/README.md @@ -41,7 +41,15 @@ -二分查找。 +**方法一:二分查找** + +我们定义二分查找的左边界 $l = 0$,右边界 $r = x$,然后在 $[l, r]$ 范围内查找平方根。 + +在每一步查找中,我们找出中间值 $mid = (l + r + 1) / 2$,如果 $mid > x / mid$,说明平方根在 $[l, mid - 1]$ 范围内,我们令 $r = mid - 1$;否则说明平方根在 $[mid, r]$ 范围内,我们令 $l = mid$。 + +查找结束后,返回 $l$ 即可。 + +时间复杂度 $O(\log x)$,空间复杂度 $O(1)$。 @@ -52,15 +60,14 @@ ```python class Solution: def mySqrt(self, x: int) -> int: - left, right = 0, x - while left < right: - mid = (left + right + 1) >> 1 - # mid*mid <= x - if mid <= x // mid: - left = mid + l, r = 0, x + while l < r: + mid = (l + r + 1) >> 1 + if mid > x // mid: + r = mid - 1 else: - right = mid - 1 - return left + l = mid + return l ``` ### **Java** @@ -70,17 +77,16 @@ class Solution: ```java class Solution { public int mySqrt(int x) { - int left = 0, right = x; - while (left < right) { - int mid = (left + right + 1) >>> 1; - if (mid <= x / mid) { - // mid*mid <= x - left = mid; + int l = 0, r = x; + while (l < r) { + int mid = (l + r + 1) >>> 1; + if (mid > x / mid) { + r = mid - 1; } else { - right = mid - 1; + l = mid; } } - return left; + return l; } } ``` @@ -91,15 +97,16 @@ class Solution { class Solution { public: int mySqrt(int x) { - long long left = 0, right = x; - while (left < right) { - long long mid = left + ((right - left + 1) >> 1); - if (mid <= x / mid) - left = mid; - else - right = mid - 1; + int l = 0, r = x; + while (l < r) { + int mid = (l + r + 1ll) >> 1; + if (mid > x / mid) { + r = mid - 1; + } else { + l = mid; + } } - return (int) left; + return l; } }; ``` @@ -108,16 +115,7 @@ public: ```go func mySqrt(x int) int { - left, right := 0, x - for left < right { - mid := left + (right-left+1)>>1 - if mid <= x/mid { - left = mid - } else { - right = mid - 1 - } - } - return left + return sort.Search(x+1, func(i int) bool { return i*i > x }) - 1 } ``` @@ -129,17 +127,16 @@ func mySqrt(x int) int { * @return {number} */ var mySqrt = function (x) { - let left = 0; - let right = x; - while (left < right) { - const mid = (left + right + 1) >>> 1; - if (mid <= x / mid) { - left = mid; + let [l, r] = [0, x]; + while (l < r) { + const mid = (l + r + 1) >> 1; + if (mid > x / mid) { + r = mid - 1; } else { - right = mid - 1; + l = mid; } } - return left; + return l; }; ``` @@ -148,20 +145,16 @@ var mySqrt = function (x) { ```cs public class Solution { public int MySqrt(int x) { - int left = 0, right = x; - while (left < right) - { - int mid = left + right + 1 >> 1; - if (mid <= x / mid) - { - left = mid; - } - else - { - right = mid - 1; + int l = 0, r = x; + while (l < r) { + int mid = (l + r + 1) >>> 1; + if (mid > x / mid) { + r = mid - 1; + } else { + l = mid; } } - return left; + return l; } } ``` @@ -171,19 +164,19 @@ public class Solution { ```rust impl Solution { pub fn my_sqrt(x: i32) -> i32 { - if x < 2 { - return x; - } - let mut l = 1; - let mut r = x / 2; + let mut l = 0; + let mut r = x; + while l < r { - let mid = (l + r + 1) >> 1; - if x / mid < mid { + let mid = (l + r + 1) / 2; + + if mid > x / mid { r = mid - 1; } else { l = mid; } } + l } } diff --git a/solution/0000-0099/0069.Sqrt(x)/README_EN.md b/solution/0000-0099/0069.Sqrt(x)/README_EN.md index 5ab23f99d75db..dd226d87615a5 100644 --- a/solution/0000-0099/0069.Sqrt(x)/README_EN.md +++ b/solution/0000-0099/0069.Sqrt(x)/README_EN.md @@ -38,7 +38,15 @@ ## Solutions -Binary search. +**Solution 1: Binary Search** + +We define the left boundary of the binary search as $l = 0$ and the right boundary as $r = x$, then we search for the square root within the range $[l, r]$. + +In each step of the search, we find the middle value $mid = (l + r + 1) / 2$. If $mid > x / mid$, it means the square root is within the range $[l, mid - 1]$, so we set $r = mid - 1$. Otherwise, it means the square root is within the range $[mid, r]$, so we set $l = mid$. + +After the search ends, we return $l$. + +The time complexity is $O(\log x)$, and the space complexity is $O(1)$. @@ -47,15 +55,14 @@ Binary search. ```python class Solution: def mySqrt(self, x: int) -> int: - left, right = 0, x - while left < right: - mid = (left + right + 1) >> 1 - # mid*mid <= x - if mid <= x // mid: - left = mid + l, r = 0, x + while l < r: + mid = (l + r + 1) >> 1 + if mid > x // mid: + r = mid - 1 else: - right = mid - 1 - return left + l = mid + return l ``` ### **Java** @@ -63,17 +70,16 @@ class Solution: ```java class Solution { public int mySqrt(int x) { - int left = 0, right = x; - while (left < right) { - int mid = (left + right + 1) >>> 1; - if (mid <= x / mid) { - // mid*mid <= x - left = mid; + int l = 0, r = x; + while (l < r) { + int mid = (l + r + 1) >>> 1; + if (mid > x / mid) { + r = mid - 1; } else { - right = mid - 1; + l = mid; } } - return left; + return l; } } ``` @@ -84,15 +90,16 @@ class Solution { class Solution { public: int mySqrt(int x) { - long long left = 0, right = x; - while (left < right) { - long long mid = left + ((right - left + 1) >> 1); - if (mid <= x / mid) - left = mid; - else - right = mid - 1; + int l = 0, r = x; + while (l < r) { + int mid = (l + r + 1ll) >> 1; + if (mid > x / mid) { + r = mid - 1; + } else { + l = mid; + } } - return (int) left; + return l; } }; ``` @@ -101,16 +108,7 @@ public: ```go func mySqrt(x int) int { - left, right := 0, x - for left < right { - mid := left + (right-left+1)>>1 - if mid <= x/mid { - left = mid - } else { - right = mid - 1 - } - } - return left + return sort.Search(x+1, func(i int) bool { return i*i > x }) - 1 } ``` @@ -122,17 +120,16 @@ func mySqrt(x int) int { * @return {number} */ var mySqrt = function (x) { - let left = 0; - let right = x; - while (left < right) { - const mid = (left + right + 1) >>> 1; - if (mid <= x / mid) { - left = mid; + let [l, r] = [0, x]; + while (l < r) { + const mid = (l + r + 1) >> 1; + if (mid > x / mid) { + r = mid - 1; } else { - right = mid - 1; + l = mid; } } - return left; + return l; }; ``` @@ -141,20 +138,16 @@ var mySqrt = function (x) { ```cs public class Solution { public int MySqrt(int x) { - int left = 0, right = x; - while (left < right) - { - int mid = left + right + 1 >> 1; - if (mid <= x / mid) - { - left = mid; - } - else - { - right = mid - 1; + int l = 0, r = x; + while (l < r) { + int mid = (l + r + 1) >>> 1; + if (mid > x / mid) { + r = mid - 1; + } else { + l = mid; } } - return left; + return l; } } ``` @@ -164,19 +157,19 @@ public class Solution { ```rust impl Solution { pub fn my_sqrt(x: i32) -> i32 { - if x < 2 { - return x; - } - let mut l = 1; - let mut r = x / 2; + let mut l = 0; + let mut r = x; + while l < r { - let mid = (l + r + 1) >> 1; - if x / mid < mid { + let mid = (l + r + 1) / 2; + + if mid > x / mid { r = mid - 1; } else { l = mid; } } + l } } diff --git a/solution/0000-0099/0069.Sqrt(x)/Solution.cpp b/solution/0000-0099/0069.Sqrt(x)/Solution.cpp index 00d8b634fd1d4..549861575efe3 100644 --- a/solution/0000-0099/0069.Sqrt(x)/Solution.cpp +++ b/solution/0000-0099/0069.Sqrt(x)/Solution.cpp @@ -1,14 +1,15 @@ -class Solution { -public: - int mySqrt(int x) { - long long left = 0, right = x; - while (left < right) { - long long mid = left + ((right - left + 1) >> 1); - if (mid <= x / mid) - left = mid; - else - right = mid - 1; - } - return (int) left; - } +class Solution { +public: + int mySqrt(int x) { + int l = 0, r = x; + while (l < r) { + int mid = (l + r + 1ll) >> 1; + if (mid > x / mid) { + r = mid - 1; + } else { + l = mid; + } + } + return l; + } }; \ No newline at end of file diff --git a/solution/0000-0099/0069.Sqrt(x)/Solution.cs b/solution/0000-0099/0069.Sqrt(x)/Solution.cs index df9dd04a18a41..d25afa99b044e 100644 --- a/solution/0000-0099/0069.Sqrt(x)/Solution.cs +++ b/solution/0000-0099/0069.Sqrt(x)/Solution.cs @@ -1,18 +1,14 @@ -public class Solution { - public int MySqrt(int x) { - int left = 0, right = x; - while (left < right) - { - int mid = left + right + 1 >> 1; - if (mid <= x / mid) - { - left = mid; - } - else - { - right = mid - 1; - } - } - return left; - } +public class Solution { + public int MySqrt(int x) { + int l = 0, r = x; + while (l < r) { + int mid = (l + r + 1) >>> 1; + if (mid > x / mid) { + r = mid - 1; + } else { + l = mid; + } + } + return l; + } } \ No newline at end of file diff --git a/solution/0000-0099/0069.Sqrt(x)/Solution.go b/solution/0000-0099/0069.Sqrt(x)/Solution.go index 8f02fb8246179..de456c6dbd843 100644 --- a/solution/0000-0099/0069.Sqrt(x)/Solution.go +++ b/solution/0000-0099/0069.Sqrt(x)/Solution.go @@ -1,12 +1,3 @@ func mySqrt(x int) int { - left, right := 0, x - for left < right { - mid := left + (right-left+1)>>1 - if mid <= x/mid { - left = mid - } else { - right = mid - 1 - } - } - return left + return sort.Search(x+1, func(i int) bool { return i*i > x }) - 1 } \ No newline at end of file diff --git a/solution/0000-0099/0069.Sqrt(x)/Solution.java b/solution/0000-0099/0069.Sqrt(x)/Solution.java index a12ffd3491700..560733a31219a 100644 --- a/solution/0000-0099/0069.Sqrt(x)/Solution.java +++ b/solution/0000-0099/0069.Sqrt(x)/Solution.java @@ -1,15 +1,14 @@ -class Solution { - public int mySqrt(int x) { - int left = 0, right = x; - while (left < right) { - int mid = (left + right + 1) >>> 1; - if (mid <= x / mid) { - // mid*mid <= x - left = mid; - } else { - right = mid - 1; - } - } - return left; - } +class Solution { + public int mySqrt(int x) { + int l = 0, r = x; + while (l < r) { + int mid = (l + r + 1) >>> 1; + if (mid > x / mid) { + r = mid - 1; + } else { + l = mid; + } + } + return l; + } } \ No newline at end of file diff --git a/solution/0000-0099/0069.Sqrt(x)/Solution.js b/solution/0000-0099/0069.Sqrt(x)/Solution.js index dd08e3a5b2de0..5c636c70c8a0e 100644 --- a/solution/0000-0099/0069.Sqrt(x)/Solution.js +++ b/solution/0000-0099/0069.Sqrt(x)/Solution.js @@ -3,15 +3,14 @@ * @return {number} */ var mySqrt = function (x) { - let left = 0; - let right = x; - while (left < right) { - const mid = (left + right + 1) >>> 1; - if (mid <= x / mid) { - left = mid; + let [l, r] = [0, x]; + while (l < r) { + const mid = (l + r + 1) >> 1; + if (mid > x / mid) { + r = mid - 1; } else { - right = mid - 1; + l = mid; } } - return left; + return l; }; diff --git a/solution/0000-0099/0069.Sqrt(x)/Solution.py b/solution/0000-0099/0069.Sqrt(x)/Solution.py index 3dbd89891be27..fca95d48efe35 100644 --- a/solution/0000-0099/0069.Sqrt(x)/Solution.py +++ b/solution/0000-0099/0069.Sqrt(x)/Solution.py @@ -1,11 +1,10 @@ -class Solution: - def mySqrt(self, x: int) -> int: - left, right = 0, x - while left < right: - mid = (left + right + 1) >> 1 - # mid*mid <= x - if mid <= x // mid: - left = mid - else: - right = mid - 1 - return left +class Solution: + def mySqrt(self, x: int) -> int: + l, r = 0, x + while l < r: + mid = (l + r + 1) >> 1 + if mid > x // mid: + r = mid - 1 + else: + l = mid + return l diff --git a/solution/0000-0099/0069.Sqrt(x)/Solution.rs b/solution/0000-0099/0069.Sqrt(x)/Solution.rs index 5e596f21681ae..6447e91c349bd 100644 --- a/solution/0000-0099/0069.Sqrt(x)/Solution.rs +++ b/solution/0000-0099/0069.Sqrt(x)/Solution.rs @@ -1,18 +1,18 @@ impl Solution { pub fn my_sqrt(x: i32) -> i32 { - if x < 2 { - return x; - } - let mut l = 1; - let mut r = x / 2; + let mut l = 0; + let mut r = x; + while l < r { - let mid = (l + r + 1) >> 1; - if x / mid < mid { + let mid = (l + r + 1) / 2; + + if mid > x / mid { r = mid - 1; } else { l = mid; } } + l } } diff --git a/solution/0000-0099/0082.Remove Duplicates from Sorted List II/README.md b/solution/0000-0099/0082.Remove Duplicates from Sorted List II/README.md index 8a05af0777f72..495942d745533 100644 --- a/solution/0000-0099/0082.Remove Duplicates from Sorted List II/README.md +++ b/solution/0000-0099/0082.Remove Duplicates from Sorted List II/README.md @@ -46,7 +46,7 @@ 最后,返回 $dummy.next$ 即可。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为链表的长度。 +时间复杂度 $O(n)$,其中 $n$ 为链表的长度。空间复杂度 $O(1)$。 diff --git a/solution/0000-0099/0083.Remove Duplicates from Sorted List/README.md b/solution/0000-0099/0083.Remove Duplicates from Sorted List/README.md index 0a8c8738a23f5..8f8f371f7ccc3 100644 --- a/solution/0000-0099/0083.Remove Duplicates from Sorted List/README.md +++ b/solution/0000-0099/0083.Remove Duplicates from Sorted List/README.md @@ -38,6 +38,14 @@ +**方法一:一次遍历** + +我们用一个指针 $cur$ 来遍历链表。如果当前 $cur$ 与 $cur.next$ 对应的元素相同,我们就将 $cur$ 的 $next$ 指针指向 $cur$ 的下下个节点。否则,说明链表中 $cur$ 对应的元素是不重复的,因此可以将 $cur$ 指针移动到下一个节点。 + +遍历结束后,返回链表的头节点即可。 + +时间复杂度 $O(n)$,其中 $n$ 是链表的长度。空间复杂度 $O(1)$。 + ### **Python3** @@ -61,25 +69,6 @@ class Solution: return head ``` -```python -# Definition for singly-linked list. -# class ListNode: -# def __init__(self, val=0, next=None): -# self.val = val -# self.next = next -class Solution: - def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: - dummy = ListNode(1000) - cur = dummy - while head: - if head.val != cur.val: - cur.next = head - cur = cur.next - head = head.next - cur.next = None - return dummy.next -``` - ### **Java** @@ -142,19 +131,53 @@ public: ### **Go** ```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ func deleteDuplicates(head *ListNode) *ListNode { - current := head - for current != nil && current.Next != nil { - if current.Val == current.Next.Val { - current.Next = current.Next.Next + cur := head + for cur != nil && cur.Next != nil { + if cur.Val == cur.Next.Val { + cur.Next = cur.Next.Next } else { - current = current.Next + cur = cur.Next } } return head } ``` +### **JavaScript** + +```js +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +var deleteDuplicates = function (head) { + let cur = head; + while (cur && cur.next) { + if (cur.next.val === cur.val) { + cur.next = cur.next.next; + } else { + cur = cur.next; + } + } + return head; +}; +``` + ### **Rust** ```rust @@ -192,6 +215,35 @@ impl Solution { } ``` +### **C#** + +```cs +/** + * Definition for singly-linked list. + * public class ListNode { + * public int val; + * public ListNode next; + * public ListNode(int val=0, ListNode next=null) { + * this.val = val; + * this.next = next; + * } + * } + */ +public class Solution { + public ListNode DeleteDuplicates(ListNode head) { + ListNode cur = head; + while (cur != null && cur.next != null) { + if (cur.val == cur.next.val) { + cur.next = cur.next.next; + } else { + cur = cur.next; + } + } + return head; + } +} +``` + ### **...** ``` diff --git a/solution/0000-0099/0083.Remove Duplicates from Sorted List/README_EN.md b/solution/0000-0099/0083.Remove Duplicates from Sorted List/README_EN.md index b52477b7ddb26..b0bc0625fea77 100644 --- a/solution/0000-0099/0083.Remove Duplicates from Sorted List/README_EN.md +++ b/solution/0000-0099/0083.Remove Duplicates from Sorted List/README_EN.md @@ -32,6 +32,14 @@ ## Solutions +**Solution 1: Single Pass** + +We use a pointer $cur$ to traverse the linked list. If the element corresponding to the current $cur$ is the same as the element corresponding to $cur.next$, we set the $next$ pointer of $cur$ to point to the next node of $cur.next$. Otherwise, it means that the element corresponding to $cur$ in the linked list is not duplicated, so we can move the $cur$ pointer to the next node. + +After the traversal ends, return the head node of the linked list. + +The time complexity is $O(n)$, where $n$ is the length of the linked list. The space complexity is $O(1)$. + ### **Python3** @@ -53,25 +61,6 @@ class Solution: return head ``` -```python -# Definition for singly-linked list. -# class ListNode: -# def __init__(self, val=0, next=None): -# self.val = val -# self.next = next -class Solution: - def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: - dummy = ListNode(1000) - cur = dummy - while head: - if head.val != cur.val: - cur.next = head - cur = cur.next - head = head.next - cur.next = None - return dummy.next -``` - ### **Java** ```java @@ -132,19 +121,53 @@ public: ### **Go** ```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ func deleteDuplicates(head *ListNode) *ListNode { - current := head - for current != nil && current.Next != nil { - if current.Val == current.Next.Val { - current.Next = current.Next.Next + cur := head + for cur != nil && cur.Next != nil { + if cur.Val == cur.Next.Val { + cur.Next = cur.Next.Next } else { - current = current.Next + cur = cur.Next } } return head } ``` +### **JavaScript** + +```js +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +var deleteDuplicates = function (head) { + let cur = head; + while (cur && cur.next) { + if (cur.next.val === cur.val) { + cur.next = cur.next.next; + } else { + cur = cur.next; + } + } + return head; +}; +``` + ### **Rust** ```rust @@ -182,6 +205,35 @@ impl Solution { } ``` +### **C#** + +```cs +/** + * Definition for singly-linked list. + * public class ListNode { + * public int val; + * public ListNode next; + * public ListNode(int val=0, ListNode next=null) { + * this.val = val; + * this.next = next; + * } + * } + */ +public class Solution { + public ListNode DeleteDuplicates(ListNode head) { + ListNode cur = head; + while (cur != null && cur.next != null) { + if (cur.val == cur.next.val) { + cur.next = cur.next.next; + } else { + cur = cur.next; + } + } + return head; + } +} +``` + ### **...** ``` diff --git a/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.cs b/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.cs index 5f9e8e23efb1f..45e7529f37c69 100644 --- a/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.cs +++ b/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.cs @@ -1,21 +1,24 @@ -public class Solution { - public ListNode DeleteDuplicates(ListNode head) { - if (head == null) return null; - var last = head; - var current = head.next; - while (current != null) - { - if (current.val != last.val) - { - last.next = current; - last = current; - } - else - { - last.next = null; - } - current = current.next; - } - return head; - } +/** + * Definition for singly-linked list. + * public class ListNode { + * public int val; + * public ListNode next; + * public ListNode(int val=0, ListNode next=null) { + * this.val = val; + * this.next = next; + * } + * } + */ +public class Solution { + public ListNode DeleteDuplicates(ListNode head) { + ListNode cur = head; + while (cur != null && cur.next != null) { + if (cur.val == cur.next.val) { + cur.next = cur.next.next; + } else { + cur = cur.next; + } + } + return head; + } } \ No newline at end of file diff --git a/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.go b/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.go index 3118fd44f729b..2131115ef4a30 100644 --- a/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.go +++ b/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.go @@ -1,10 +1,17 @@ +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ func deleteDuplicates(head *ListNode) *ListNode { - current := head - for current != nil && current.Next != nil { - if current.Val == current.Next.Val { - current.Next = current.Next.Next + cur := head + for cur != nil && cur.Next != nil { + if cur.Val == cur.Next.Val { + cur.Next = cur.Next.Next } else { - current = current.Next + cur = cur.Next } } return head diff --git a/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.js b/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.js index 4ae37df7b4f4f..b03ee8343a388 100644 --- a/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.js +++ b/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.js @@ -10,12 +10,12 @@ * @return {ListNode} */ var deleteDuplicates = function (head) { - var p = head; - while (p && p.next) { - if (p.val == p.next.val) { - p.next = p.next.next; + let cur = head; + while (cur && cur.next) { + if (cur.next.val === cur.val) { + cur.next = cur.next.next; } else { - p = p.next; + cur = cur.next; } } return head; diff --git a/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.py b/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.py index 960f14ce47981..25c52cd0afe39 100644 --- a/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.py +++ b/solution/0000-0099/0083.Remove Duplicates from Sorted List/Solution.py @@ -1,14 +1,14 @@ -# Definition for singly-linked list. -# class ListNode: -# def __init__(self, val=0, next=None): -# self.val = val -# self.next = next -class Solution: - def deleteDuplicates(self, head: ListNode) -> ListNode: - cur = head - while cur and cur.next: - if cur.val == cur.next.val: - cur.next = cur.next.next - else: - cur = cur.next - return head +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + cur = head + while cur and cur.next: + if cur.val == cur.next.val: + cur.next = cur.next.next + else: + cur = cur.next + return head diff --git a/solution/0000-0099/0095.Unique Binary Search Trees II/README.md b/solution/0000-0099/0095.Unique Binary Search Trees II/README.md index 7568b82e50fc3..9e98d72d78544 100644 --- a/solution/0000-0099/0095.Unique Binary Search Trees II/README.md +++ b/solution/0000-0099/0095.Unique Binary Search Trees II/README.md @@ -40,6 +40,17 @@ +**方法一:DFS** + +我们设计一个函数 $dfs(i, j)$,返回由 $[i, j]$ 组成的所有可行的二叉搜索树,那么答案就是 $dfs(1, n)$。 + +函数 $dfs(i, j)$ 的执行步骤如下: + +1. 如果 $i > j$,那么说明此时没有数字可以构成二叉搜索树,返回由一个空节点组成的列表。 +2. 如果 $i \leq j$,那么我们枚举 $[i, j]$ 中的数字 $v$ 作为根节点,那么根节点 $v$ 的左子树由 $[i, v - 1]$ 组成,右子树由 $[v + 1, j]$ 组成,最后将左右子树的所有组合笛卡尔积,即 $left \times right$,加上根节点 $v$,得到以 $v$ 为根节点的所有二叉搜索树。 + +时间复杂度 $O(n \times G(n))$,空间复杂度 $O(n \times G(n))$。其中 $G(n)$ 是卡特兰数。 + ### **Python3** @@ -54,22 +65,20 @@ # self.left = left # self.right = right class Solution: - def generateTrees(self, n: int) -> List[TreeNode]: - def gen(left, right): + def generateTrees(self, n: int) -> List[Optional[TreeNode]]: + def dfs(i: int, j: int) -> List[Optional[TreeNode]]: + if i > j: + return [None] ans = [] - if left > right: - ans.append(None) - else: - for i in range(left, right + 1): - left_trees = gen(left, i - 1) - right_trees = gen(i + 1, right) - for l in left_trees: - for r in right_trees: - node = TreeNode(i, l, r) - ans.append(node) + for v in range(i, j + 1): + left = dfs(i, v - 1) + right = dfs(v + 1, j) + for l in left: + for r in right: + ans.append(TreeNode(v, l, r)) return ans - return gen(1, n) + return dfs(1, n) ``` ### **Java** @@ -94,22 +103,21 @@ class Solution: */ class Solution { public List generateTrees(int n) { - return generateTrees(1, n); + return dfs(1, n); } - private List generateTrees(int left, int right) { + private List dfs(int i, int j) { List ans = new ArrayList<>(); - if (left > right) { + if (i > j) { ans.add(null); - } else { - for (int i = left; i <= right; ++i) { - List leftTrees = generateTrees(left, i - 1); - List rightTrees = generateTrees(i + 1, right); - for (TreeNode l : leftTrees) { - for (TreeNode r : rightTrees) { - TreeNode node = new TreeNode(i, l, r); - ans.add(node); - } + return ans; + } + for (int v = i; v <= j; ++v) { + var left = dfs(i, v - 1); + var right = dfs(v + 1, j); + for (var l : left) { + for (var r : right) { + ans.add(new TreeNode(v, l, r)); } } } @@ -118,48 +126,6 @@ class Solution { } ``` -### **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 generateTrees(n: number): Array { - if (n == 0) return []; - return helper(1, n); -} - -function helper(start: number, end: number): Array { - let ans = []; - if (start > end) { - ans.push(null); - return ans; - } - for (let i = start; i <= end; i++) { - let lefts = helper(start, i - 1); - let rights = helper(i + 1, end); - for (let left of lefts) { - for (let right of rights) { - let root = new TreeNode(i, left, right); - ans.push(root); - } - } - } - return ans; -} -``` - ### **C++** ```cpp @@ -177,28 +143,96 @@ function helper(start: number, end: number): Array { class Solution { public: vector generateTrees(int n) { - return gen(1, n); + function(int, int)> dfs = [&](int i, int j) { + if (i > j) { + return vector{nullptr}; + } + vector ans; + for (int v = i; v <= j; ++v) { + auto left = dfs(i, v - 1); + auto right = dfs(v + 1, j); + for (auto l : left) { + for (auto r : right) { + ans.push_back(new TreeNode(v, l, r)); + } + } + } + return ans; + }; + return dfs(1, n); } +}; +``` - vector gen(int left, int right) { - vector ans; - if (left > right) { - ans.push_back(nullptr); - } else { - for (int i = left; i <= right; ++i) { - auto leftTrees = gen(left, i - 1); - auto rightTrees = gen(i + 1, right); - for (auto& l : leftTrees) { - for (auto& r : rightTrees) { - TreeNode* node = new TreeNode(i, l, r); - ans.push_back(node); - } +### **Go** + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func generateTrees(n int) []*TreeNode { + var dfs func(int, int) []*TreeNode + dfs = func(i, j int) []*TreeNode { + if i > j { + return []*TreeNode{nil} + } + ans := []*TreeNode{} + for v := i; v <= j; v++ { + left := dfs(i, v-1) + right := dfs(v+1, j) + for _, l := range left { + for _, r := range right { + ans = append(ans, &TreeNode{v, l, r}) + } + } + } + return ans + } + return dfs(1, n) +} +``` + +### **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 generateTrees(n: number): Array { + const dfs = (i: number, j: number): Array => { + if (i > j) { + return [null]; + } + const ans: Array = []; + for (let v = i; v <= j; ++v) { + const left = dfs(i, v - 1); + const right = dfs(v + 1, j); + for (const l of left) { + for (const r of right) { + ans.push(new TreeNode(v, l, r)); } } } return ans; - } -}; + }; + return dfs(1, n); +} ``` ### **Rust** @@ -225,82 +259,40 @@ public: use std::rc::Rc; use std::cell::RefCell; impl Solution { - #[allow(dead_code)] pub fn generate_trees(n: i32) -> Vec>>> { - Self::generate_trees_inner(1, n) + Self::dfs(1, n) } - #[allow(dead_code)] - fn generate_trees_inner(left: i32, right: i32) -> Vec>>> { - let mut ret = Vec::new(); - - if left > right { - // If there is no possible BST matching - // Then this should be consider a nullptr - ret.push(None); - } else { - // Otherwise, let's generate the BST - for i in left..=right { - // First get the two vectors containing the possible left trees & right trees - let left_trees = Self::generate_trees_inner(left, i - 1); - let right_trees = Self::generate_trees_inner(i + 1, right); - - // Then construct the final results - for left_tree in &left_trees { - for right_tree in &right_trees { - // Construct the current node - let mut node = Some(Rc::new(RefCell::new(TreeNode::new(i)))); - // Set the connection - node.as_ref().unwrap().borrow_mut().left = left_tree.clone(); - node.as_ref().unwrap().borrow_mut().right = right_tree.clone(); - // Update the result vector - ret.push(node); - } + fn dfs(i: i32, j: i32) -> Vec>>> { + let mut ans = Vec::new(); + if i > j { + ans.push(None); + return ans; + } + for v in i..=j { + let left = Self::dfs(i, v - 1); + let right = Self::dfs(v + 1, j); + for l in &left { + for r in &right { + ans.push( + Some( + Rc::new( + RefCell::new(TreeNode { + val: v, + left: l.clone(), + right: r.clone(), + }) + ) + ) + ); } } } - - ret + ans } } ``` -### **Go** - -```go -/** - * Definition for a binary tree node. - * type TreeNode struct { - * Val int - * Left *TreeNode - * Right *TreeNode - * } - */ -func generateTrees(n int) []*TreeNode { - var gen func(left, right int) []*TreeNode - gen = func(left, right int) []*TreeNode { - var ans []*TreeNode - if left > right { - ans = append(ans, nil) - } else { - for i := left; i <= right; i++ { - leftTrees := gen(left, i-1) - rightTrees := gen(i+1, right) - for _, l := range leftTrees { - for _, r := range rightTrees { - node := &TreeNode{i, l, r} - ans = append(ans, node) - } - } - } - } - return ans - } - - return gen(1, n) -} -``` - ### **...** ``` diff --git a/solution/0000-0099/0095.Unique Binary Search Trees II/README_EN.md b/solution/0000-0099/0095.Unique Binary Search Trees II/README_EN.md index 8b384cbabda13..aa14f32268808 100644 --- a/solution/0000-0099/0095.Unique Binary Search Trees II/README_EN.md +++ b/solution/0000-0099/0095.Unique Binary Search Trees II/README_EN.md @@ -30,6 +30,17 @@ ## Solutions +**Solution 1: DFS (Depth-First Search)** + +We design a function $dfs(i, j)$ that returns all feasible binary search trees composed of $[i, j]$, so the answer is $dfs(1, n)$. + +The execution steps of the function $dfs(i, j)$ are as follows: + +1. If $i > j$, it means that there are no numbers to form a binary search tree at this time, so return a list consisting of a null node. +2. If $i \leq j$, we enumerate the numbers $v$ in $[i, j]$ as the root node. The left subtree of the root node $v$ is composed of $[i, v - 1]$, and the right subtree is composed of $[v + 1, j]$. Finally, we take the Cartesian product of all combinations of the left and right subtrees, i.e., $left \times right$, add the root node $v$, and get all binary search trees with $v$ as the root node. + +The time complexity is $O(n \times G(n))$, and the space complexity is $O(n \times G(n))$. Where $G(n)$ is the Catalan number. + ### **Python3** @@ -42,22 +53,20 @@ # self.left = left # self.right = right class Solution: - def generateTrees(self, n: int) -> List[TreeNode]: - def gen(left, right): + def generateTrees(self, n: int) -> List[Optional[TreeNode]]: + def dfs(i: int, j: int) -> List[Optional[TreeNode]]: + if i > j: + return [None] ans = [] - if left > right: - ans.append(None) - else: - for i in range(left, right + 1): - left_trees = gen(left, i - 1) - right_trees = gen(i + 1, right) - for l in left_trees: - for r in right_trees: - node = TreeNode(i, l, r) - ans.append(node) + for v in range(i, j + 1): + left = dfs(i, v - 1) + right = dfs(v + 1, j) + for l in left: + for r in right: + ans.append(TreeNode(v, l, r)) return ans - return gen(1, n) + return dfs(1, n) ``` ### **Java** @@ -80,22 +89,21 @@ class Solution: */ class Solution { public List generateTrees(int n) { - return generateTrees(1, n); + return dfs(1, n); } - private List generateTrees(int left, int right) { + private List dfs(int i, int j) { List ans = new ArrayList<>(); - if (left > right) { + if (i > j) { ans.add(null); - } else { - for (int i = left; i <= right; ++i) { - List leftTrees = generateTrees(left, i - 1); - List rightTrees = generateTrees(i + 1, right); - for (TreeNode l : leftTrees) { - for (TreeNode r : rightTrees) { - TreeNode node = new TreeNode(i, l, r); - ans.add(node); - } + return ans; + } + for (int v = i; v <= j; ++v) { + var left = dfs(i, v - 1); + var right = dfs(v + 1, j); + for (var l : left) { + for (var r : right) { + ans.add(new TreeNode(v, l, r)); } } } @@ -104,48 +112,6 @@ class Solution { } ``` -### **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 generateTrees(n: number): Array { - if (n == 0) return []; - return helper(1, n); -} - -function helper(start: number, end: number): Array { - let ans = []; - if (start > end) { - ans.push(null); - return ans; - } - for (let i = start; i <= end; i++) { - let lefts = helper(start, i - 1); - let rights = helper(i + 1, end); - for (let left of lefts) { - for (let right of rights) { - let root = new TreeNode(i, left, right); - ans.push(root); - } - } - } - return ans; -} -``` - ### **C++** ```cpp @@ -163,28 +129,96 @@ function helper(start: number, end: number): Array { class Solution { public: vector generateTrees(int n) { - return gen(1, n); + function(int, int)> dfs = [&](int i, int j) { + if (i > j) { + return vector{nullptr}; + } + vector ans; + for (int v = i; v <= j; ++v) { + auto left = dfs(i, v - 1); + auto right = dfs(v + 1, j); + for (auto l : left) { + for (auto r : right) { + ans.push_back(new TreeNode(v, l, r)); + } + } + } + return ans; + }; + return dfs(1, n); } +}; +``` - vector gen(int left, int right) { - vector ans; - if (left > right) { - ans.push_back(nullptr); - } else { - for (int i = left; i <= right; ++i) { - auto leftTrees = gen(left, i - 1); - auto rightTrees = gen(i + 1, right); - for (auto& l : leftTrees) { - for (auto& r : rightTrees) { - TreeNode* node = new TreeNode(i, l, r); - ans.push_back(node); - } +### **Go** + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func generateTrees(n int) []*TreeNode { + var dfs func(int, int) []*TreeNode + dfs = func(i, j int) []*TreeNode { + if i > j { + return []*TreeNode{nil} + } + ans := []*TreeNode{} + for v := i; v <= j; v++ { + left := dfs(i, v-1) + right := dfs(v+1, j) + for _, l := range left { + for _, r := range right { + ans = append(ans, &TreeNode{v, l, r}) + } + } + } + return ans + } + return dfs(1, n) +} +``` + +### **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 generateTrees(n: number): Array { + const dfs = (i: number, j: number): Array => { + if (i > j) { + return [null]; + } + const ans: Array = []; + for (let v = i; v <= j; ++v) { + const left = dfs(i, v - 1); + const right = dfs(v + 1, j); + for (const l of left) { + for (const r of right) { + ans.push(new TreeNode(v, l, r)); } } } return ans; - } -}; + }; + return dfs(1, n); +} ``` ### **Rust** @@ -211,82 +245,40 @@ public: use std::rc::Rc; use std::cell::RefCell; impl Solution { - #[allow(dead_code)] pub fn generate_trees(n: i32) -> Vec>>> { - Self::generate_trees_inner(1, n) + Self::dfs(1, n) } - #[allow(dead_code)] - fn generate_trees_inner(left: i32, right: i32) -> Vec>>> { - let mut ret = Vec::new(); - - if left > right { - // If there is no possible BST matching - // Then this should be consider a nullptr - ret.push(None); - } else { - // Otherwise, let's generate the BST - for i in left..=right { - // First get the two vectors containing the possible left trees & right trees - let left_trees = Self::generate_trees_inner(left, i - 1); - let right_trees = Self::generate_trees_inner(i + 1, right); - - // Then construct the final results - for left_tree in &left_trees { - for right_tree in &right_trees { - // Construct the current node - let mut node = Some(Rc::new(RefCell::new(TreeNode::new(i)))); - // Set the connection - node.as_ref().unwrap().borrow_mut().left = left_tree.clone(); - node.as_ref().unwrap().borrow_mut().right = right_tree.clone(); - // Update the result vector - ret.push(node); - } + fn dfs(i: i32, j: i32) -> Vec>>> { + let mut ans = Vec::new(); + if i > j { + ans.push(None); + return ans; + } + for v in i..=j { + let left = Self::dfs(i, v - 1); + let right = Self::dfs(v + 1, j); + for l in &left { + for r in &right { + ans.push( + Some( + Rc::new( + RefCell::new(TreeNode { + val: v, + left: l.clone(), + right: r.clone(), + }) + ) + ) + ); } } } - - ret + ans } } ``` -### **Go** - -```go -/** - * Definition for a binary tree node. - * type TreeNode struct { - * Val int - * Left *TreeNode - * Right *TreeNode - * } - */ -func generateTrees(n int) []*TreeNode { - var gen func(left, right int) []*TreeNode - gen = func(left, right int) []*TreeNode { - var ans []*TreeNode - if left > right { - ans = append(ans, nil) - } else { - for i := left; i <= right; i++ { - leftTrees := gen(left, i-1) - rightTrees := gen(i+1, right) - for _, l := range leftTrees { - for _, r := range rightTrees { - node := &TreeNode{i, l, r} - ans = append(ans, node) - } - } - } - } - return ans - } - - return gen(1, n) -} -``` - ### **...** ``` diff --git a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.cpp b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.cpp index a88f9250b8106..4f362fd516f63 100644 --- a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.cpp +++ b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.cpp @@ -1,36 +1,33 @@ -/** - * Definition for a binary tree node. - * struct TreeNode { - * int val; - * TreeNode *left; - * TreeNode *right; - * TreeNode() : val(0), left(nullptr), right(nullptr) {} - * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} - * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} - * }; - */ -class Solution { -public: - vector generateTrees(int n) { - return gen(1, n); - } - - vector gen(int left, int right) { - vector ans; - if (left > right) { - ans.push_back(nullptr); - } else { - for (int i = left; i <= right; ++i) { - auto leftTrees = gen(left, i - 1); - auto rightTrees = gen(i + 1, right); - for (auto& l : leftTrees) { - for (auto& r : rightTrees) { - TreeNode* node = new TreeNode(i, l, r); - ans.push_back(node); - } - } - } - } - return ans; - } +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector generateTrees(int n) { + function(int, int)> dfs = [&](int i, int j) { + if (i > j) { + return vector{nullptr}; + } + vector ans; + for (int v = i; v <= j; ++v) { + auto left = dfs(i, v - 1); + auto right = dfs(v + 1, j); + for (auto l : left) { + for (auto r : right) { + ans.push_back(new TreeNode(v, l, r)); + } + } + } + return ans; + }; + return dfs(1, n); + } }; \ No newline at end of file diff --git a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.go b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.go index 5a3b1eddcc251..b6bda843e2bda 100644 --- a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.go +++ b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.go @@ -7,25 +7,22 @@ * } */ func generateTrees(n int) []*TreeNode { - var gen func(left, right int) []*TreeNode - gen = func(left, right int) []*TreeNode { - var ans []*TreeNode - if left > right { - ans = append(ans, nil) - } else { - for i := left; i <= right; i++ { - leftTrees := gen(left, i-1) - rightTrees := gen(i+1, right) - for _, l := range leftTrees { - for _, r := range rightTrees { - node := &TreeNode{i, l, r} - ans = append(ans, node) - } + var dfs func(int, int) []*TreeNode + dfs = func(i, j int) []*TreeNode { + if i > j { + return []*TreeNode{nil} + } + ans := []*TreeNode{} + for v := i; v <= j; v++ { + left := dfs(i, v-1) + right := dfs(v+1, j) + for _, l := range left { + for _, r := range right { + ans = append(ans, &TreeNode{v, l, r}) } } } return ans } - - return gen(1, n) + return dfs(1, n) } \ No newline at end of file diff --git a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.java b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.java index 47ace6b1da2b6..94c1c81e49f58 100644 --- a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.java +++ b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.java @@ -1,39 +1,38 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ -class Solution { - public List generateTrees(int n) { - return generateTrees(1, n); - } - - private List generateTrees(int left, int right) { - List ans = new ArrayList<>(); - if (left > right) { - ans.add(null); - } else { - for (int i = left; i <= right; ++i) { - List leftTrees = generateTrees(left, i - 1); - List rightTrees = generateTrees(i + 1, right); - for (TreeNode l : leftTrees) { - for (TreeNode r : rightTrees) { - TreeNode node = new TreeNode(i, l, r); - ans.add(node); - } - } - } - } - return ans; - } +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List generateTrees(int n) { + return dfs(1, n); + } + + private List dfs(int i, int j) { + List ans = new ArrayList<>(); + if (i > j) { + ans.add(null); + return ans; + } + for (int v = i; v <= j; ++v) { + var left = dfs(i, v - 1); + var right = dfs(v + 1, j); + for (var l : left) { + for (var r : right) { + ans.add(new TreeNode(v, l, r)); + } + } + } + return ans; + } } \ No newline at end of file diff --git a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.py b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.py index 44c0e8c3a13d5..19f94c8c32f62 100644 --- a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.py +++ b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.py @@ -1,23 +1,21 @@ -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right -class Solution: - def generateTrees(self, n: int) -> List[TreeNode]: - def gen(left, right): - ans = [] - if left > right: - ans.append(None) - else: - for i in range(left, right + 1): - left_trees = gen(left, i - 1) - right_trees = gen(i + 1, right) - for l in left_trees: - for r in right_trees: - node = TreeNode(i, l, r) - ans.append(node) - return ans - - return gen(1, n) +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def generateTrees(self, n: int) -> List[Optional[TreeNode]]: + def dfs(i: int, j: int) -> List[Optional[TreeNode]]: + if i > j: + return [None] + ans = [] + for v in range(i, j + 1): + left = dfs(i, v - 1) + right = dfs(v + 1, j) + for l in left: + for r in right: + ans.append(TreeNode(v, l, r)) + return ans + + return dfs(1, n) diff --git a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.rs b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.rs index a32acb576c953..c2772b463d772 100644 --- a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.rs +++ b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.rs @@ -19,41 +19,35 @@ use std::rc::Rc; use std::cell::RefCell; impl Solution { - #[allow(dead_code)] pub fn generate_trees(n: i32) -> Vec>>> { - Self::generate_trees_inner(1, n) + Self::dfs(1, n) } - #[allow(dead_code)] - fn generate_trees_inner(left: i32, right: i32) -> Vec>>> { - let mut ret = Vec::new(); - - if left > right { - // If there is no possible BST matching - // Then this should be consider a nullptr - ret.push(None); - } else { - // Otherwise, let's generate the BST - for i in left..=right { - // First get the two vectors containing the possible left trees & right trees - let left_trees = Self::generate_trees_inner(left, i - 1); - let right_trees = Self::generate_trees_inner(i + 1, right); - - // Then construct the final results - for left_tree in &left_trees { - for right_tree in &right_trees { - // Construct the current node - let mut node = Some(Rc::new(RefCell::new(TreeNode::new(i)))); - // Set the connection - node.as_ref().unwrap().borrow_mut().left = left_tree.clone(); - node.as_ref().unwrap().borrow_mut().right = right_tree.clone(); - // Update the result vector - ret.push(node); - } + fn dfs(i: i32, j: i32) -> Vec>>> { + let mut ans = Vec::new(); + if i > j { + ans.push(None); + return ans; + } + for v in i..=j { + let left = Self::dfs(i, v - 1); + let right = Self::dfs(v + 1, j); + for l in &left { + for r in &right { + ans.push( + Some( + Rc::new( + RefCell::new(TreeNode { + val: v, + left: l.clone(), + right: r.clone(), + }) + ) + ) + ); } } } - - ret + ans } } diff --git a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.ts b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.ts index e009a73cd0d0e..3e3e473e03d24 100644 --- a/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.ts +++ b/solution/0000-0099/0095.Unique Binary Search Trees II/Solution.ts @@ -13,25 +13,21 @@ */ function generateTrees(n: number): Array { - if (n == 0) return []; - return helper(1, n); -} - -function helper(start: number, end: number): Array { - let ans = []; - if (start > end) { - ans.push(null); - return ans; - } - for (let i = start; i <= end; i++) { - let lefts = helper(start, i - 1); - let rights = helper(i + 1, end); - for (let left of lefts) { - for (let right of rights) { - let root = new TreeNode(i, left, right); - ans.push(root); + const dfs = (i: number, j: number): Array => { + if (i > j) { + return [null]; + } + const ans: Array = []; + for (let v = i; v <= j; ++v) { + const left = dfs(i, v - 1); + const right = dfs(v + 1, j); + for (const l of left) { + for (const r of right) { + ans.push(new TreeNode(v, l, r)); + } } } - } - return ans; + return ans; + }; + return dfs(1, n); } diff --git a/solution/2700-2799/2706.Buy Two Chocolates/README.md b/solution/2700-2799/2706.Buy Two Chocolates/README.md index c059fbad26640..be992ef4dfcbc 100644 --- a/solution/2700-2799/2706.Buy Two Chocolates/README.md +++ b/solution/2700-2799/2706.Buy Two Chocolates/README.md @@ -48,7 +48,7 @@ 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组 `prices` 的长度。 -**方法一:一次遍历** +**方法二:一次遍历** 我们可以在一次遍历中找到最小的两个价格,然后计算花费。 diff --git a/solution/README.md b/solution/README.md index 14af0538165f6..eba9b5b731541 100644 --- a/solution/README.md +++ b/solution/README.md @@ -102,6 +102,7 @@ | 0089 | [格雷编码](/solution/0000-0099/0089.Gray%20Code/README.md) | `位运算`,`数学`,`回溯` | 中等 | | | 0090 | [子集 II](/solution/0000-0099/0090.Subsets%20II/README.md) | `位运算`,`数组`,`回溯` | 中等 | | | 0091 | [解码方法](/solution/0000-0099/0091.Decode%20Ways/README.md) | `字符串`,`动态规划` | 中等 | | +| 0092 | [反转链表 II](/solution/0000-0099/0092.Reverse%20Linked%20List%20II/README.md) | `链表` | 中等 | | | 0093 | [复原 IP 地址](/solution/0000-0099/0093.Restore%20IP%20Addresses/README.md) | `字符串`,`回溯` | 中等 | | | 0094 | [二叉树的中序遍历](/solution/0000-0099/0094.Binary%20Tree%20Inorder%20Traversal/README.md) | `栈`,`树`,`深度优先搜索`,`二叉树` | 简单 | | | 0095 | [不同的二叉搜索树 II](/solution/0000-0099/0095.Unique%20Binary%20Search%20Trees%20II/README.md) | `树`,`二叉搜索树`,`动态规划`,`回溯`,`二叉树` | 中等 | | @@ -368,6 +369,7 @@ | 0356 | [直线镜像](/solution/0300-0399/0356.Line%20Reflection/README.md) | `数组`,`哈希表`,`数学` | 中等 | 🔒 | | 0357 | [统计各位数字都不同的数字个数](/solution/0300-0399/0357.Count%20Numbers%20with%20Unique%20Digits/README.md) | `数学`,`动态规划`,`回溯` | 中等 | | | 0358 | [K 距离间隔重排字符串](/solution/0300-0399/0358.Rearrange%20String%20k%20Distance%20Apart/README.md) | `贪心`,`哈希表`,`字符串`,`计数`,`排序`,`堆(优先队列)` | 困难 | 🔒 | +| 0359 | [日志速率限制器](/solution/0300-0399/0359.Logger%20Rate%20Limiter/README.md) | `设计`,`哈希表`,`数据流` | 简单 | 🔒 | | 0360 | [有序转化数组](/solution/0300-0399/0360.Sort%20Transformed%20Array/README.md) | `数组`,`数学`,`双指针`,`排序` | 中等 | 🔒 | | 0361 | [轰炸敌人](/solution/0300-0399/0361.Bomb%20Enemy/README.md) | `数组`,`动态规划`,`矩阵` | 中等 | 🔒 | | 0362 | [敲击计数器](/solution/0300-0399/0362.Design%20Hit%20Counter/README.md) | `设计`,`队列`,`数组`,`哈希表`,`二分查找` | 中等 | 🔒 | @@ -375,6 +377,8 @@ | 0364 | [嵌套列表加权和 II](/solution/0300-0399/0364.Nested%20List%20Weight%20Sum%20II/README.md) | `栈`,`深度优先搜索`,`广度优先搜索` | 中等 | 🔒 | | 0365 | [水壶问题](/solution/0300-0399/0365.Water%20and%20Jug%20Problem/README.md) | `深度优先搜索`,`广度优先搜索`,`数学` | 中等 | | | 0366 | [寻找二叉树的叶子节点](/solution/0300-0399/0366.Find%20Leaves%20of%20Binary%20Tree/README.md) | `树`,`深度优先搜索`,`二叉树` | 中等 | 🔒 | +| 0367 | [有效的完全平方数](/solution/0300-0399/0367.Valid%20Perfect%20Square/README.md) | `数学`,`二分查找` | 简单 | | +| 0368 | [最大整除子集](/solution/0300-0399/0368.Largest%20Divisible%20Subset/README.md) | `数组`,`数学`,`动态规划`,`排序` | 中等 | | | 0369 | [给单链表加一](/solution/0300-0399/0369.Plus%20One%20Linked%20List/README.md) | `链表`,`数学` | 中等 | 🔒 | | 0370 | [区间加法](/solution/0300-0399/0370.Range%20Addition/README.md) | `数组`,`前缀和` | 中等 | 🔒 | | 0371 | [两整数之和](/solution/0300-0399/0371.Sum%20of%20Two%20Integers/README.md) | `位运算`,`数学` | 中等 | | @@ -2985,7 +2989,7 @@ | 2976 | [转换字符串的最小成本 I](/solution/2900-2999/2976.Minimum%20Cost%20to%20Convert%20String%20I/README.md) | | 中等 | 第 377 场周赛 | | 2977 | [转换字符串的最小成本 II](/solution/2900-2999/2977.Minimum%20Cost%20to%20Convert%20String%20II/README.md) | | 困难 | 第 377 场周赛 | | 2978 | [Symmetric Coordinates](/solution/2900-2999/2978.Symmetric%20Coordinates/README.md) | | 中等 | 🔒 | -| 2979 | [Most Expensive Item That Can Not Be Bought](/solution/2900-2999/2979.Most%20Expensive%20Item%20That%20Can%20Not%20Be%20Bought/README.md) | | 中等 | 🔒 | +| 2979 | [最贵的无法购买的商品](/solution/2900-2999/2979.Most%20Expensive%20Item%20That%20Can%20Not%20Be%20Bought/README.md) | | 中等 | 🔒 | ## 版权 diff --git a/solution/README_EN.md b/solution/README_EN.md index 0520cd12005d3..d760d55defdbd 100644 --- a/solution/README_EN.md +++ b/solution/README_EN.md @@ -100,6 +100,7 @@ Press Control + F(or Command + F on | 0089 | [Gray Code](/solution/0000-0099/0089.Gray%20Code/README_EN.md) | `Bit Manipulation`,`Math`,`Backtracking` | Medium | | | 0090 | [Subsets II](/solution/0000-0099/0090.Subsets%20II/README_EN.md) | `Bit Manipulation`,`Array`,`Backtracking` | Medium | | | 0091 | [Decode Ways](/solution/0000-0099/0091.Decode%20Ways/README_EN.md) | `String`,`Dynamic Programming` | Medium | | +| 0092 | [Reverse Linked List II](/solution/0000-0099/0092.Reverse%20Linked%20List%20II/README_EN.md) | `Linked List` | Medium | | | 0093 | [Restore IP Addresses](/solution/0000-0099/0093.Restore%20IP%20Addresses/README_EN.md) | `String`,`Backtracking` | Medium | | | 0094 | [Binary Tree Inorder Traversal](/solution/0000-0099/0094.Binary%20Tree%20Inorder%20Traversal/README_EN.md) | `Stack`,`Tree`,`Depth-First Search`,`Binary Tree` | Easy | | | 0095 | [Unique Binary Search Trees II](/solution/0000-0099/0095.Unique%20Binary%20Search%20Trees%20II/README_EN.md) | `Tree`,`Binary Search Tree`,`Dynamic Programming`,`Backtracking`,`Binary Tree` | Medium | | @@ -366,6 +367,7 @@ Press Control + F(or Command + F on | 0356 | [Line Reflection](/solution/0300-0399/0356.Line%20Reflection/README_EN.md) | `Array`,`Hash Table`,`Math` | Medium | 🔒 | | 0357 | [Count Numbers with Unique Digits](/solution/0300-0399/0357.Count%20Numbers%20with%20Unique%20Digits/README_EN.md) | `Math`,`Dynamic Programming`,`Backtracking` | Medium | | | 0358 | [Rearrange String k Distance Apart](/solution/0300-0399/0358.Rearrange%20String%20k%20Distance%20Apart/README_EN.md) | `Greedy`,`Hash Table`,`String`,`Counting`,`Sorting`,`Heap (Priority Queue)` | Hard | 🔒 | +| 0359 | [Logger Rate Limiter](/solution/0300-0399/0359.Logger%20Rate%20Limiter/README_EN.md) | `Design`,`Hash Table`,`Data Stream` | Easy | 🔒 | | 0360 | [Sort Transformed Array](/solution/0300-0399/0360.Sort%20Transformed%20Array/README_EN.md) | `Array`,`Math`,`Two Pointers`,`Sorting` | Medium | 🔒 | | 0361 | [Bomb Enemy](/solution/0300-0399/0361.Bomb%20Enemy/README_EN.md) | `Array`,`Dynamic Programming`,`Matrix` | Medium | 🔒 | | 0362 | [Design Hit Counter](/solution/0300-0399/0362.Design%20Hit%20Counter/README_EN.md) | `Design`,`Queue`,`Array`,`Hash Table`,`Binary Search` | Medium | 🔒 | @@ -373,6 +375,8 @@ Press Control + F(or Command + F on | 0364 | [Nested List Weight Sum II](/solution/0300-0399/0364.Nested%20List%20Weight%20Sum%20II/README_EN.md) | `Stack`,`Depth-First Search`,`Breadth-First Search` | Medium | 🔒 | | 0365 | [Water and Jug Problem](/solution/0300-0399/0365.Water%20and%20Jug%20Problem/README_EN.md) | `Depth-First Search`,`Breadth-First Search`,`Math` | Medium | | | 0366 | [Find Leaves of Binary Tree](/solution/0300-0399/0366.Find%20Leaves%20of%20Binary%20Tree/README_EN.md) | `Tree`,`Depth-First Search`,`Binary Tree` | Medium | 🔒 | +| 0367 | [Valid Perfect Square](/solution/0300-0399/0367.Valid%20Perfect%20Square/README_EN.md) | `Math`,`Binary Search` | Easy | | +| 0368 | [Largest Divisible Subset](/solution/0300-0399/0368.Largest%20Divisible%20Subset/README_EN.md) | `Array`,`Math`,`Dynamic Programming`,`Sorting` | Medium | | | 0369 | [Plus One Linked List](/solution/0300-0399/0369.Plus%20One%20Linked%20List/README_EN.md) | `Linked List`,`Math` | Medium | 🔒 | | 0370 | [Range Addition](/solution/0300-0399/0370.Range%20Addition/README_EN.md) | `Array`,`Prefix Sum` | Medium | 🔒 | | 0371 | [Sum of Two Integers](/solution/0300-0399/0371.Sum%20of%20Two%20Integers/README_EN.md) | `Bit Manipulation`,`Math` | Medium | | diff --git a/solution/main.py b/solution/main.py index 97f2685fa9a15..6ccd1aea55b07 100644 --- a/solution/main.py +++ b/solution/main.py @@ -395,7 +395,7 @@ def run(): except: slug = q['titleSlug'] qid = int(q['frontendQuestionId']) - if slug in question_details and qid < 2960: + if slug in question_details: continue detail = spider.get_question_detail( slug, retry=4 diff --git a/solution/summary.md b/solution/summary.md index 991d6f6337965..6fc88726cbc5b 100644 --- a/solution/summary.md +++ b/solution/summary.md @@ -91,7 +91,7 @@ - [0089.格雷编码](/solution/0000-0099/0089.Gray%20Code/README.md) - [0090.子集 II](/solution/0000-0099/0090.Subsets%20II/README.md) - [0091.解码方法](/solution/0000-0099/0091.Decode%20Ways/README.md) - - [0092.Reverse Linked List II](/solution/0000-0099/0092.Reverse%20Linked%20List%20II/README.md) + - [0092.反转链表 II](/solution/0000-0099/0092.Reverse%20Linked%20List%20II/README.md) - [0093.复原 IP 地址](/solution/0000-0099/0093.Restore%20IP%20Addresses/README.md) - [0094.二叉树的中序遍历](/solution/0000-0099/0094.Binary%20Tree%20Inorder%20Traversal/README.md) - [0095.不同的二叉搜索树 II](/solution/0000-0099/0095.Unique%20Binary%20Search%20Trees%20II/README.md) @@ -364,7 +364,7 @@ - [0356.直线镜像](/solution/0300-0399/0356.Line%20Reflection/README.md) - [0357.统计各位数字都不同的数字个数](/solution/0300-0399/0357.Count%20Numbers%20with%20Unique%20Digits/README.md) - [0358.K 距离间隔重排字符串](/solution/0300-0399/0358.Rearrange%20String%20k%20Distance%20Apart/README.md) - - [0359.Logger Rate Limiter](/solution/0300-0399/0359.Logger%20Rate%20Limiter/README.md) + - [0359.日志速率限制器](/solution/0300-0399/0359.Logger%20Rate%20Limiter/README.md) - [0360.有序转化数组](/solution/0300-0399/0360.Sort%20Transformed%20Array/README.md) - [0361.轰炸敌人](/solution/0300-0399/0361.Bomb%20Enemy/README.md) - [0362.敲击计数器](/solution/0300-0399/0362.Design%20Hit%20Counter/README.md) @@ -372,8 +372,8 @@ - [0364.嵌套列表加权和 II](/solution/0300-0399/0364.Nested%20List%20Weight%20Sum%20II/README.md) - [0365.水壶问题](/solution/0300-0399/0365.Water%20and%20Jug%20Problem/README.md) - [0366.寻找二叉树的叶子节点](/solution/0300-0399/0366.Find%20Leaves%20of%20Binary%20Tree/README.md) - - [0367.Valid Perfect Square](/solution/0300-0399/0367.Valid%20Perfect%20Square/README.md) - - [0368.Largest Divisible Subset](/solution/0300-0399/0368.Largest%20Divisible%20Subset/README.md) + - [0367.有效的完全平方数](/solution/0300-0399/0367.Valid%20Perfect%20Square/README.md) + - [0368.最大整除子集](/solution/0300-0399/0368.Largest%20Divisible%20Subset/README.md) - [0369.给单链表加一](/solution/0300-0399/0369.Plus%20One%20Linked%20List/README.md) - [0370.区间加法](/solution/0300-0399/0370.Range%20Addition/README.md) - [0371.两整数之和](/solution/0300-0399/0371.Sum%20of%20Two%20Integers/README.md) @@ -3036,4 +3036,4 @@ - [2976.转换字符串的最小成本 I](/solution/2900-2999/2976.Minimum%20Cost%20to%20Convert%20String%20I/README.md) - [2977.转换字符串的最小成本 II](/solution/2900-2999/2977.Minimum%20Cost%20to%20Convert%20String%20II/README.md) - [2978.Symmetric Coordinates](/solution/2900-2999/2978.Symmetric%20Coordinates/README.md) - - [2979.Most Expensive Item That Can Not Be Bought](/solution/2900-2999/2979.Most%20Expensive%20Item%20That%20Can%20Not%20Be%20Bought/README.md) + - [2979.最贵的无法购买的商品](/solution/2900-2999/2979.Most%20Expensive%20Item%20That%20Can%20Not%20Be%20Bought/README.md)