From f2f04cf4b7f46f716130c533bbea8431cb9aa4c6 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Thu, 4 Jan 2024 19:06:56 +0800 Subject: [PATCH] feat: add solutions to lc problems: No.200+ --- .../0213.House Robber II/README_EN.md | 6 ++++++ .../README.md | 10 ++++----- .../README_EN.md | 14 +++++++++++++ .../0217.Contains Duplicate/README_EN.md | 16 ++++++++++++++ .../0220.Contains Duplicate III/README.md | 4 ++-- .../0220.Contains Duplicate III/README_EN.md | 8 +++++++ .../0221.Maximal Square/README_EN.md | 16 ++++++++++++++ .../README_EN.md | 21 +++++++++++++++++++ .../0223.Rectangle Area/README_EN.md | 6 ++++++ .../0224.Basic Calculator/README_EN.md | 16 ++++++++++++++ .../README_EN.md | 11 ++++++++++ .../0226.Invert Binary Tree/README_EN.md | 6 +++++- .../0227.Basic Calculator II/README_EN.md | 12 +++++++++++ 13 files changed, 138 insertions(+), 8 deletions(-) diff --git a/solution/0200-0299/0213.House Robber II/README_EN.md b/solution/0200-0299/0213.House Robber II/README_EN.md index 1f0bfad00e1f2..67b8c2293a634 100644 --- a/solution/0200-0299/0213.House Robber II/README_EN.md +++ b/solution/0200-0299/0213.House Robber II/README_EN.md @@ -43,6 +43,12 @@ Total amount you can rob = 1 + 3 = 4. ## Solutions +**Solution 1: Dynamic Programming** + +The circular arrangement means that at most one of the first and last houses can be chosen for theft, so this circular arrangement problem can be reduced to two single-row house problems. + +The time complexity is $O(n)$, where $n$ is the length of the array. The space complexity is $O(1)$. + ### **Python3** diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md index 5b6551d134cd0..8844384653068 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md @@ -42,15 +42,15 @@ **方法一:排序** -将数组 $nums$ 升序排列,然后获取 $nums[n-k]$。 +我们可以将数组 $nums$ 升序排列,然后获取 $nums[n-k]$。 -时间复杂度 $O(nlogn)$,其中 $n$ 表示数组 $nums$ 的长度。 +时间复杂度 $O(n \times \log n)$,其中 $n$ 表示数组 $nums$ 的长度。 -**方法二:partition** +**方法二:Partition** -并不是所有时候,都需要整个数组进入有序状态,只需要**局部有序**,或者说,从大到小排序,只要 $[0..k)$ 位置的元素有序,那么就能确定结果,此处使用**快速排序**。 +我们注意到,并不是所有时候,都需要整个数组进入有序状态,只需要**局部有序**,或者说,从大到小排序,只要 $[0..k)$ 位置的元素有序,那么就能确定结果,此处使用**快速排序**。 -快速排序有一特点,每一次循环结束时,能够确定的是:$partition$ 一定处于它该处于的索引位置。从而根据它得知,结果值是在左数组还是在右数组当中,然后对那一数组进行排序即可。 +快速排序有一特点,每一次循环结束时,能够确定的是 $partition$ 一定处于它该处于的索引位置。从而根据它得知,结果值是在左数组还是在右数组当中,然后对那一数组进行排序即可。 时间复杂度 $O(n)$,其中 $n$ 表示数组 $nums$ 的长度。 diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md index 081c6b677b2f2..6affc376986cd 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md @@ -28,6 +28,20 @@ ## Solutions +**Solution 1: Sorting** + +We can sort the array $nums$ in ascending order, and then get $nums[n-k]$. + +The time complexity is $O(n \times \log n)$, where $n$ is the length of the array $nums$. + +**Solution 2: Partition** + +We notice that it is not always necessary for the entire array to be in an ordered state. We only need **local order**. That is to say, if the elements in the position $[0..k)$ are sorted in descending order, then we can determine the result. Here we use **quick sort**. + +Quick sort has a characteristic that at the end of each loop, it can be determined that the $partition$ is definitely at the index position it should be. Therefore, based on it, we know whether the result value is in the left array or in the right array, and then sort that array. + +The time complexity is $O(n)$, where $n$ is the length of the array $nums$. + ### **Python3** diff --git a/solution/0200-0299/0217.Contains Duplicate/README_EN.md b/solution/0200-0299/0217.Contains Duplicate/README_EN.md index 05aeeaaf91dee..cde49fa4fdfe8 100644 --- a/solution/0200-0299/0217.Contains Duplicate/README_EN.md +++ b/solution/0200-0299/0217.Contains Duplicate/README_EN.md @@ -27,6 +27,22 @@ ## Solutions +**Solution 1: Sorting** + +First, we sort the array `nums`. + +Then, we traverse the array. If there are two adjacent elements that are the same, it means that there are duplicate elements in the array, and we directly return `true`. + +Otherwise, when the traversal ends, we return `false`. + +The time complexity is $O(n \times \log n)$, where $n$ is the length of the array `nums`. + +**Solution 2: Hash Table** + +We traverse the array and record the elements that have appeared in the hash table $s$. If an element appears for the second time, it means that there are duplicate elements in the array, and we directly return `true`. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array `nums`. + ### **Python3** diff --git a/solution/0200-0299/0220.Contains Duplicate III/README.md b/solution/0200-0299/0220.Contains Duplicate III/README.md index 582cc5b832b8f..54dfb7617f710 100644 --- a/solution/0200-0299/0220.Contains Duplicate III/README.md +++ b/solution/0200-0299/0220.Contains Duplicate III/README.md @@ -57,11 +57,11 @@ abs(nums[i] - nums[j]) <= valueDiff --> abs(1 - 1) <= 0 **方法一:滑动窗口 + 有序集合** -维护一个大小为 $k$ 的滑动窗口,窗口中的元素保持有序。 +我们维护一个大小为 $k$ 的滑动窗口,窗口中的元素保持有序。 遍历数组 `nums`,对于每个元素 $nums[i]$,我们在有序集合中查找第一个大于等于 $nums[i] - t$ 的元素,如果元素存在,并且该元素小于等于 $nums[i] + t$,说明找到了一对符合条件的元素,返回 `true`。否则,我们将 $nums[i]$ 插入到有序集合中,并且如果有序集合的大小超过了 $k$,我们需要将最早加入有序集合的元素删除。 -时间复杂度 $O(n\times \log k)$,其中 $n$ 是数组 `nums` 的长度。对于每个元素,我们需要 $O(\log k)$ 的时间来查找有序集合中的元素,一共有 $n$ 个元素,因此总时间复杂度是 $O(n\times \log k)$。 +时间复杂度 $O(n \times \log k)$,其中 $n$ 是数组 `nums` 的长度。对于每个元素,我们需要 $O(\log k)$ 的时间来查找有序集合中的元素,一共有 $n$ 个元素,因此总时间复杂度是 $O(n \times \log k)$。 diff --git a/solution/0200-0299/0220.Contains Duplicate III/README_EN.md b/solution/0200-0299/0220.Contains Duplicate III/README_EN.md index bfa825b5a1643..8bebf53420607 100644 --- a/solution/0200-0299/0220.Contains Duplicate III/README_EN.md +++ b/solution/0200-0299/0220.Contains Duplicate III/README_EN.md @@ -49,6 +49,14 @@ abs(nums[i] - nums[j]) <= valueDiff --> abs(1 - 1) <= 0 ## Solutions +**Solution 1: Sliding Window + Ordered Set** + +We maintain a sliding window of size $k$, and the elements in the window are kept in order. + +We traverse the array `nums`. For each element $nums[i]$, we look for the first element in the ordered set that is greater than or equal to $nums[i] - t$. If the element exists, and this element is less than or equal to $nums[i] + t$, it means we have found a pair of elements that meet the conditions, and we return `true`. Otherwise, we insert $nums[i]$ into the ordered set, and if the size of the ordered set exceeds $k$, we need to remove the earliest added element from the ordered set. + +The time complexity is $O(n \times \log k)$, where $n$ is the length of the array `nums`. For each element, we need $O(\log k)$ time to find the element in the ordered set, and there are $n$ elements in total, so the total time complexity is $O(n \times \log k)$. + ### **Python3** diff --git a/solution/0200-0299/0221.Maximal Square/README_EN.md b/solution/0200-0299/0221.Maximal Square/README_EN.md index f5aab7f408ae2..0456a72b08b8e 100644 --- a/solution/0200-0299/0221.Maximal Square/README_EN.md +++ b/solution/0200-0299/0221.Maximal Square/README_EN.md @@ -40,6 +40,22 @@ ## Solutions +**Solution 1: Dynamic Programming** + +We define $dp[i + 1][j + 1]$ as the maximum square side length with the lower right corner at index $(i, j)$. The answer is the maximum value among all $dp[i + 1][j + 1]$. + +The state transition equation is: + +$$ +dp[i + 1][j + 1] = +\begin{cases} +0 & \text{if } matrix[i][j] = '0' \\ +\min(dp[i][j], dp[i][j + 1], dp[i + 1][j]) + 1 & \text{if } matrix[i][j] = '1' +\end{cases} +$$ + +The time complexity is $O(m\times n)$, and the space complexity is $O(m\times n)$. Where $m$ and $n$ are the number of rows and columns of the matrix, respectively. + ### **Python3** diff --git a/solution/0200-0299/0222.Count Complete Tree Nodes/README_EN.md b/solution/0200-0299/0222.Count Complete Tree Nodes/README_EN.md index 7f510b5038c56..e6104a8cf22c5 100644 --- a/solution/0200-0299/0222.Count Complete Tree Nodes/README_EN.md +++ b/solution/0200-0299/0222.Count Complete Tree Nodes/README_EN.md @@ -43,6 +43,27 @@ ## Solutions +**Solution 1: Recursion** + +We recursively traverse the entire tree and count the number of nodes. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the number of nodes in the tree. + +**Solution 2: Binary Search** + +For this problem, we can also take advantage of the characteristics of a complete binary tree to design a faster algorithm. + +Characteristics of a complete binary tree: leaf nodes can only appear on the bottom and second-to-bottom layers, and the leaf nodes on the bottom layer are concentrated on the left side of the tree. It should be noted that a full binary tree is definitely a complete binary tree, but a complete binary tree is not necessarily a full binary tree. + +If the number of layers in a full binary tree is $h$, then the total number of nodes is $2^h - 1$. + +We first count the heights of the left and right subtrees of $root$, denoted as $left$ and $right$. + +1. If $left = right$, it means that the left subtree is a full binary tree, so the total number of nodes in the left subtree is $2^{left} - 1$. Plus the $root$ node, it is $2^{left}$. Then we recursively count the right subtree. +1. If $left > right$, it means that the right subtree is a full binary tree, so the total number of nodes in the right subtree is $2^{right} - 1$. Plus the $root$ node, it is $2^{right}$. Then we recursively count the left subtree. + +The time complexity is $O(\log^2 n)$. + ### **Python3** diff --git a/solution/0200-0299/0223.Rectangle Area/README_EN.md b/solution/0200-0299/0223.Rectangle Area/README_EN.md index a7ba8a164d858..05808907edecc 100644 --- a/solution/0200-0299/0223.Rectangle Area/README_EN.md +++ b/solution/0200-0299/0223.Rectangle Area/README_EN.md @@ -37,6 +37,12 @@ ## Solutions +**Solution 1: Calculate Overlapping Area** + +First, we calculate the area of the two rectangles separately, denoted as $a$ and $b$. Then we calculate the overlapping width $width$ and height $height$. The overlapping area is $max(width, 0) \times max(height, 0)$. Finally, we subtract the overlapping area from $a$ and $b$. + +The time complexity is $O(1)$, and the space complexity is $O(1)$. + ### **Python3** diff --git a/solution/0200-0299/0224.Basic Calculator/README_EN.md b/solution/0200-0299/0224.Basic Calculator/README_EN.md index a269d86edbc44..a8ef63b124ac6 100644 --- a/solution/0200-0299/0224.Basic Calculator/README_EN.md +++ b/solution/0200-0299/0224.Basic Calculator/README_EN.md @@ -45,6 +45,22 @@ ## Solutions +**Solution 1: Stack** + +We use a stack $stk$ to save the current calculation result and operator, a variable $sign$ to save the current sign, and a variable $ans$ to save the final calculation result. + +Next, we traverse each character of the string $s$: + +- If the current character is a number, we use a loop to read the following consecutive numbers, and then add or subtract it to $ans$ according to the current sign. +- If the current character is `'+'`, we change the variable $sign$ to positive. +- If the current character is `'-'`, we change the variable $sign$ to negative. +- If the current character is `'('`, we push the current $ans$ and $sign$ into the stack, and reset them to empty and 1, and start to calculate the new $ans$ and $sign$. +- If the current character is `')'`, we pop the top two elements of the stack, one is the operator, and the other is the number calculated before the bracket. We multiply the current number by the operator, and add the previous number to get the new $ans$. + +After traversing the string $s$, we return $ans$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the string $s$. + ### **Python3** 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 c8cf55fbf22cf..23c1d86d92681 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 @@ -55,6 +55,17 @@ myStack.empty(); // return False ## Solutions +**Solution 1: Two Queues** + +We use two queues $q_1$ and $q_2$, where $q_1$ is used to store the elements in the stack, and $q_2$ is used to assist in implementing the stack operations. + +- `push` operation: Push the element into $q_2$, then pop the elements in $q_1$ one by one and push them into $q_2$, finally swap the references of $q_1$ and $q_2$. The time complexity is $O(n)$. +- `pop` operation: Directly pop the front element of $q_1$. The time complexity is $O(1)$. +- `top` operation: Directly return the front element of $q_1$. The time complexity is $O(1)$. +- `empty` operation: Check whether $q_1$ is empty. The time complexity is $O(1)$. + +The space complexity is $O(n)$, where $n$ is the number of elements in the stack. + ### **Python3** 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 e2ad513a37d39..428d6ce77f8c4 100644 --- a/solution/0200-0299/0226.Invert Binary Tree/README_EN.md +++ b/solution/0200-0299/0226.Invert Binary Tree/README_EN.md @@ -38,7 +38,11 @@ ## Solutions -DFS. +**Solution 1: Recursion** + +The idea of recursion is very simple, which is to swap the left and right subtrees of the current node, and then recursively swap the left and right subtrees of the current node. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the number of nodes in the binary tree. diff --git a/solution/0200-0299/0227.Basic Calculator II/README_EN.md b/solution/0200-0299/0227.Basic Calculator II/README_EN.md index c999fff2444a4..0ec8175c09705 100644 --- a/solution/0200-0299/0227.Basic Calculator II/README_EN.md +++ b/solution/0200-0299/0227.Basic Calculator II/README_EN.md @@ -36,6 +36,18 @@ ## Solutions +**Solution 1: Stack** + +We traverse the string $s$, and use a variable `sign` to record the operator before each number. For the first number, its previous operator is considered as a plus sign. Each time we traverse to the end of a number, we decide the calculation method based on `sign`: + +- Plus sign: push the number into the stack; +- Minus sign: push the opposite number into the stack; +- Multiplication and division signs: calculate the number with the top element of the stack, and replace the top element of the stack with the calculation result. + +After the traversal ends, the sum of the elements in the stack is the answer. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the string $s$. + ### **Python3**