Skip to content

Commit f42ff99

Browse files
authored
feat: update solutions to lc problems (doocs#3451)
1 parent e152696 commit f42ff99

File tree

7 files changed

+130
-35
lines changed

7 files changed

+130
-35
lines changed

solution/1300-1399/1326.Minimum Number of Taps to Open to Water a Garden/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ tags:
7575

7676
我们注意到,对于所有能覆盖某个左端点的水龙头,选择能覆盖最远右端点的那个水龙头是最优的。
7777

78-
因此,我们可以先预处理数组 $ranges$,对于第 $i$ 个水龙头,它能覆盖的左端点 $l = max(0, i - ranges[i])$,右端点 $r = i + ranges[i]$,我们算出所有能覆盖左端点 $l$ 的水龙头中,右端点最大的那个位置,记录在数组 $last[i]$ 中。
78+
因此,我们可以先预处理数组 $ranges$,对于第 $i$ 个水龙头,它能覆盖的左端点 $l = \max(0, i - ranges[i])$,右端点 $r = i + ranges[i]$,我们算出所有能覆盖左端点 $l$ 的水龙头中,右端点最大的那个位置,记录在数组 $last[i]$ 中。
7979

8080
然后我们定义以下三个变量,其中:
8181

8282
- 变量 $ans$ 表示最终答案,即最少水龙头数目;
8383
- 变量 $mx$ 表示当前能覆盖的最远右端点;
8484
- 变量 $pre$ 表示上一个水龙头覆盖的最远右端点。
8585

86-
我们在 $[0,...n-1]$ 的范围内遍历所有位置,对于当前位置 $i$,我们用 $last[i]$ 更新 $mx$,即 $mx = max(mx, last[i])$。
86+
我们在 $[0,...n-1]$ 的范围内遍历所有位置,对于当前位置 $i$,我们用 $last[i]$ 更新 $mx$,即 $mx = \max(mx, last[i])$。
8787

8888
- 如果 $mx \leq i$,说明无法覆盖下一个位置,返回 $-1$。
8989
- 如果 $pre = i$,说明需要使用一个新的子区间,因此我们将 $ans$ 加 $1$,并且更新 $pre = mx$。

solution/1300-1399/1326.Minimum Number of Taps to Open to Water a Garden/README_EN.md

+26-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,32 @@ Opening Only the second tap will water the whole garden [0,5]
6666

6767
<!-- solution:start -->
6868

69-
### Solution 1
69+
### Solution 1: Greedy
70+
71+
We note that for all taps that can cover a certain left endpoint, choosing the tap that can cover the farthest right endpoint is optimal.
72+
73+
Therefore, we can preprocess the array $ranges$. For the $i$-th tap, it can cover the left endpoint $l = \max(0, i - ranges[i])$ and the right endpoint $r = i + ranges[i]$. We calculate the position of the tap that can cover the left endpoint $l$ with the farthest right endpoint and record it in the array $last[i]$.
74+
75+
Then we define the following three variables:
76+
77+
- Variable $ans$ represents the final answer, i.e., the minimum number of taps;
78+
- Variable $mx$ represents the farthest right endpoint that can currently be covered;
79+
- Variable $pre$ represents the farthest right endpoint covered by the previous tap.
80+
81+
We traverse all positions in the range $[0, \ldots, n-1]$. For the current position $i$, we use $last[i]$ to update $mx$, i.e., $mx = \max(mx, last[i])$.
82+
83+
- If $mx \leq i$, it means the next position cannot be covered, so we return $-1$.
84+
- If $pre = i$, it means a new subinterval needs to be used, so we increment $ans$ by $1$ and update $pre = mx$.
85+
86+
After the traversal, we return $ans$.
87+
88+
The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the garden.
89+
90+
Similar problems:
91+
92+
- [45. Jump Game II](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0045.Jump%20Game%20II/README.md)
93+
- [55. Jump Game](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0055.Jump%20Game/README.md)
94+
- [1024. Video Stitching](https://github.com/doocs/leetcode/blob/main/solution/1000-1099/1024.Video%20Stitching/README.md)
7095

7196
<!-- tabs:start -->
7297

solution/1300-1399/1328.Break a Palindrome/README_EN.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,13 @@ Of all the ways, &quot;aaccba&quot; is the lexicographically smallest.
5757

5858
<!-- solution:start -->
5959

60-
### Solution 1
60+
### Solution 1: Greedy
61+
62+
First, we check if the length of the string is $1$. If it is, we directly return an empty string.
63+
64+
Otherwise, we traverse the first half of the string from left to right, find the first character that is not `'a'`, and change it to `'a'`. If no such character exists, we change the last character to `'b'`.
65+
66+
The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string.
6167

6268
<!-- tabs:start -->
6369

solution/1300-1399/1330.Reverse Subarray To Maximize Array Value/README_EN.md

+46-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,52 @@ tags:
5757

5858
<!-- solution:start -->
5959

60-
### Solution 1
60+
### Solution 1: Classification Discussion + Enumeration
61+
62+
According to the problem description, we need to find the maximum value of the array $\sum_{i=0}^{n-2} |a_i - a_{i+1}|$ when reversing a subarray once.
63+
64+
Next, we discuss the following cases:
65+
66+
1. Do not reverse the subarray.
67+
2. Reverse the subarray, and the subarray "includes" the first element.
68+
3. Reverse the subarray, and the subarray "includes" the last element.
69+
4. Reverse the subarray, and the subarray "does not include" the first and last elements.
70+
71+
Let $s$ be the array value when the subarray is not reversed, then $s = \sum_{i=0}^{n-2} |a_i - a_{i+1}|$. We can initialize the answer $ans$ to $s$.
72+
73+
If we reverse the subarray and the subarray includes the first element, we can enumerate the last element $a_i$ of the reversed subarray, where $0 \leq i < n-1$. In this case, $ans = \max(ans, s + |a_0 - a_{i+1}| - |a_i - a_{i+1}|)$.
74+
75+
<p><img alt="" src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/1300-1399/1330.Reverse%20Subarray%20To%20Maximize%20Array%20Value/images/1-drawio.png" /></p>
76+
77+
Similarly, if we reverse the subarray and the subarray includes the last element, we can enumerate the first element $a_{i+1}$ of the reversed subarray, where $0 \leq i < n-1$. In this case, $ans = \max(ans, s + |a_{n-1} - a_i| - |a_i - a_{i+1}|)$.
78+
79+
<p><img alt="" src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/1300-1399/1330.Reverse%20Subarray%20To%20Maximize%20Array%20Value/images/2-drawio.png" /></p>
80+
81+
If we reverse the subarray and the subarray does not include the first and last elements, we consider any two adjacent elements in the array as a point pair $(x, y)$. Let the first element of the reversed subarray be $y_1$, and its left adjacent element be $x_1$; let the last element of the reversed subarray be $x_2$, and its right adjacent element be $y_2$.
82+
83+
<p><img alt="" src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/1300-1399/1330.Reverse%20Subarray%20To%20Maximize%20Array%20Value/images/3-drawio.png" /></p>
84+
85+
At this time, compared to not reversing the subarray, the change in the array value is $|x_1 - x_2| + |y_1 - y_2| - |x_1 - y_1| - |x_2 - y_2|$, where the first two terms can be expressed as:
86+
87+
$$
88+
\left | x_1 - x_2 \right | + \left | y_1 - y_2 \right | = \max \begin{cases} (x_1 + y_1) - (x_2 + y_2) \\ (x_1 - y_1) - (x_2 - y_2) \\ (-x_1 + y_1) - (-x_2 + y_2) \\ (-x_1 - y_1) - (-x_2 - y_2) \end{cases}
89+
$$
90+
91+
Then the change in the array value is:
92+
93+
$$
94+
\left | x_1 - x_2 \right | + \left | y_1 - y_2 \right | - \left | x_1 - y_1 \right | - \left | x_2 - y_2 \right | = \max \begin{cases} (x_1 + y_1) - \left |x_1 - y_1 \right | - \left ( (x_2 + y_2) + \left |x_2 - y_2 \right | \right ) \\ (x_1 - y_1) - \left |x_1 - y_1 \right | - \left ( (x_2 - y_2) + \left |x_2 - y_2 \right | \right ) \\ (-x_1 + y_1) - \left |x_1 - y_1 \right | - \left ( (-x_2 + y_2) + \left |x_2 - y_2 \right | \right ) \\ (-x_1 - y_1) - \left |x_1 - y_1 \right | - \left ( (-x_2 - y_2) + \left |x_2 - y_2 \right | \right ) \end{cases}
95+
$$
96+
97+
Therefore, we only need to find the maximum value $mx$ of $k_1 \times x + k_2 \times y$, where $k_1, k_2 \in \{-1, 1\}$, and the corresponding minimum value $mi$ of $|x - y|$. Then the maximum change in the array value is $mx - mi$. The answer is $ans = \max(ans, s + \max(0, mx - mi))$.
98+
99+
In the code implementation, we define an array of length 5, $dirs=[1, -1, -1, 1, 1]$. Each time we take two adjacent elements of the array as the values of $k_1$ and $k_2$, which can cover all cases of $k_1, k_2 \in \{-1, 1\}$.
100+
101+
The time complexity is $O(n)$, where $n$ is the length of the array $nums$. The space complexity is $O(1)$.
102+
103+
Similar problems:
104+
105+
- [1131. Maximum of Absolute Value Expression](https://github.com/doocs/leetcode/blob/main/solution/1100-1199/1131.Maximum%20of%20Absolute%20Value%20Expression/README_EN.md)
61106

62107
<!-- tabs:start -->
63108

solution/1300-1399/1331.Rank Transform of an Array/README_EN.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,13 @@ tags:
6767

6868
<!-- solution:start -->
6969

70-
### Solution 1
70+
### Solution 1: Discretization
71+
72+
First, we copy an array $t$, then sort and deduplicate it to obtain an array of length $m$ that is strictly monotonically increasing.
73+
74+
Next, we traverse the original array $arr$. For each element $x$ in the array, we use binary search to find the position of $x$ in $t$. The position plus one is the rank of $x$.
75+
76+
The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $arr$.
7177

7278
<!-- tabs:start -->
7379

solution/1400-1499/1409.Queries on a Permutation With Key/README.md

+18-20
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ tags:
3535

3636
<pre>
3737
<strong>输入:</strong>queries = [3,1,2,1], m = 5
38-
<strong>输出:</strong>[2,1,2,1]
38+
<strong>输出:</strong>[2,1,2,1]
3939
<strong>解释:处理</strong> queries 的过程如下:
4040
对于 i=0: queries[i]=3, P=[1,2,3,4,5], 3 在 P 中的位置是 <strong>2</strong>,然后我们把 3 移动到 P 的开头,得到 P=[3,1,2,4,5] 。
41-
对于 i=1: queries[i]=1, P=[3,1,2,4,5], 1 在 P 中的位置是 <strong>1</strong>,然后我们把 1 移动到 P 的开头,得到 P=[1,3,2,4,5] 。
41+
对于 i=1: queries[i]=1, P=[3,1,2,4,5], 1 在 P 中的位置是 <strong>1</strong>,然后我们把 1 移动到 P 的开头,得到 P=[1,3,2,4,5] 。
4242
对于 i=2: queries[i]=2, P=[1,3,2,4,5], 2 在 P 中的位置是 <strong>2</strong>,然后我们把 2 移动到 P 的开头,得到 P=[2,1,3,4,5] 。
43-
对于 i=3: queries[i]=1, P=[2,1,3,4,5], 1 在 P 中的位置是 <strong>1</strong>,然后我们把 1 移动到 P 的开头,得到 P=[1,2,3,4,5] 。
44-
因此,包含结果的数组为 [2,1,2,1] 。
43+
对于 i=3: queries[i]=1, P=[2,1,3,4,5], 1 在 P 中的位置是 <strong>1</strong>,然后我们把 1 移动到 P 的开头,得到 P=[1,2,3,4,5] 。
44+
因此,包含结果的数组为 [2,1,2,1] 。
4545
</pre>
4646

4747
<p><strong>示例 2:</strong></p>
@@ -78,21 +78,6 @@ tags:
7878

7979
题目数据规模不大,可以直接模拟。
8080

81-
**方法一:树状数组**
82-
83-
树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作:
84-
85-
1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta;
86-
1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。
87-
88-
这两个操作的时间复杂度均为 $O(\log n)$。
89-
90-
树状数组最基本的功能就是求比某点 x 小的点的个数(这里的比较是抽象的概念,可以是数的大小、坐标的大小、质量的大小等等)。
91-
92-
比如给定数组 `a[5] = {2, 5, 3, 4, 1}`,求 `b[i] = 位置 i 左边小于等于 a[i] 的数的个数`。对于此例,`b[5] = {0, 1, 1, 2, 0}`
93-
94-
解决方案是直接遍历数组,每个位置先求出 `query(a[i])`,然后再修改树状数组 `update(a[i], 1)` 即可。当数的范围比较大时,需要进行离散化,即先进行去重并排序,然后对每个数字进行编号。
95-
9681
<!-- tabs:start -->
9782

9883
#### Python3
@@ -189,7 +174,20 @@ func processQueries(queries []int, m int) []int {
189174

190175
<!-- solution:start -->
191176

192-
### 方法二
177+
### 方法二:树状数组
178+
179+
树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作:
180+
181+
1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta;
182+
1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。
183+
184+
这两个操作的时间复杂度均为 $O(\log n)$。
185+
186+
树状数组最基本的功能就是求比某点 x 小的点的个数(这里的比较是抽象的概念,可以是数的大小、坐标的大小、质量的大小等等)。
187+
188+
比如给定数组 `a[5] = {2, 5, 3, 4, 1}`,求 `b[i] = 位置 i 左边小于等于 a[i] 的数的个数`。对于此例,`b[5] = {0, 1, 1, 2, 0}`
189+
190+
解决方案是直接遍历数组,每个位置先求出 `query(a[i])`,然后再修改树状数组 `update(a[i], 1)` 即可。当数的范围比较大时,需要进行离散化,即先进行去重并排序,然后对每个数字进行编号。
193191

194192
<!-- tabs:start -->
195193

solution/1400-1499/1409.Queries on a Permutation With Key/README_EN.md

+24-9
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ tags:
3434

3535
<pre>
3636
<strong>Input:</strong> queries = [3,1,2,1], m = 5
37-
<strong>Output:</strong> [2,1,2,1]
38-
<strong>Explanation:</strong> The queries are processed as follow:
39-
For i=0: queries[i]=3, P=[1,2,3,4,5], position of 3 in P is <strong>2</strong>, then we move 3 to the beginning of P resulting in P=[3,1,2,4,5].
40-
For i=1: queries[i]=1, P=[3,1,2,4,5], position of 1 in P is <strong>1</strong>, then we move 1 to the beginning of P resulting in P=[1,3,2,4,5].
41-
For i=2: queries[i]=2, P=[1,3,2,4,5], position of 2 in P is <strong>2</strong>, then we move 2 to the beginning of P resulting in P=[2,1,3,4,5].
42-
For i=3: queries[i]=1, P=[2,1,3,4,5], position of 1 in P is <strong>1</strong>, then we move 1 to the beginning of P resulting in P=[1,2,3,4,5].
43-
Therefore, the array containing the result is [2,1,2,1].
37+
<strong>Output:</strong> [2,1,2,1]
38+
<strong>Explanation:</strong> The queries are processed as follow:
39+
For i=0: queries[i]=3, P=[1,2,3,4,5], position of 3 in P is <strong>2</strong>, then we move 3 to the beginning of P resulting in P=[3,1,2,4,5].
40+
For i=1: queries[i]=1, P=[3,1,2,4,5], position of 1 in P is <strong>1</strong>, then we move 1 to the beginning of P resulting in P=[1,3,2,4,5].
41+
For i=2: queries[i]=2, P=[1,3,2,4,5], position of 2 in P is <strong>2</strong>, then we move 2 to the beginning of P resulting in P=[2,1,3,4,5].
42+
For i=3: queries[i]=1, P=[2,1,3,4,5], position of 1 in P is <strong>1</strong>, then we move 1 to the beginning of P resulting in P=[1,2,3,4,5].
43+
Therefore, the array containing the result is [2,1,2,1].
4444
</pre>
4545

4646
<p><strong class="example">Example 2:</strong></p>
@@ -72,7 +72,9 @@ Therefore, the array containing the result is [2,1,2,1].
7272

7373
<!-- solution:start -->
7474

75-
### Solution 1
75+
### Solution 1: Simulation
76+
77+
The problem's data scale is not large, so we can directly simulate it.
7678

7779
<!-- tabs:start -->
7880

@@ -170,7 +172,20 @@ func processQueries(queries []int, m int) []int {
170172

171173
<!-- solution:start -->
172174

173-
### Solution 2
175+
### Solution 2: Binary Indexed Tree
176+
177+
The Binary Indexed Tree (BIT), also known as the Fenwick Tree, efficiently supports the following two operations:
178+
179+
1. **Point Update** `update(x, delta)`: Adds a value `delta` to the element at position `x` in the sequence.
180+
2. **Prefix Sum Query** `query(x)`: Queries the sum of the sequence over the interval `[1,...,x]`, i.e., the prefix sum at position `x`.
181+
182+
Both operations have a time complexity of $O(\log n)$.
183+
184+
The fundamental functionality of the Binary Indexed Tree is to count the number of elements smaller than a given element `x`. This comparison is abstract and can refer to size, coordinate, mass, etc.
185+
186+
For example, given the array `a[5] = {2, 5, 3, 4, 1}`, the task is to compute `b[i] = the number of elements to the left of position i that are less than or equal to a[i]`. For this example, `b[5] = {0, 1, 1, 2, 0}`.
187+
188+
The solution is to traverse the array, first calculating `query(a[i])` for each position, and then updating the Binary Indexed Tree with `update(a[i], 1)`. When the range of numbers is large, discretization is necessary, which involves removing duplicates, sorting, and then assigning an index to each number.
174189

175190
<!-- tabs:start -->
176191

0 commit comments

Comments
 (0)