Skip to content

Commit ccf55f2

Browse files
authored
feat: add solutions to lc problems: No.1471,1474,1475 (doocs#3633)
1 parent 14d5068 commit ccf55f2

File tree

30 files changed

+437
-817
lines changed

30 files changed

+437
-817
lines changed

solution/1400-1499/1471.The k Strongest Values in an Array/README.md

+16-2
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,13 @@ tags:
9090

9191
<!-- solution:start -->
9292

93-
### 方法一:自定义排序
93+
### 方法一:排序
9494

95-
时间复杂度 $O(2nlogn)$。
95+
我们首先对数组 $\textit{arr}$ 进行排序,然后找到数组的中位数 $m$。
96+
97+
接下来,我们按照题目描述的规则对数组进行排序,最后返回数组的前 $k$ 个元素即可。
98+
99+
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\textit{arr}$ 的长度。
96100

97101
<!-- tabs:start -->
98102

@@ -174,6 +178,16 @@ func abs(x int) int {
174178
}
175179
```
176180

181+
#### TypeScript
182+
183+
```ts
184+
function getStrongest(arr: number[], k: number): number[] {
185+
arr.sort((a, b) => a - b);
186+
const m = arr[(arr.length - 1) >> 1];
187+
return arr.sort((a, b) => Math.abs(b - m) - Math.abs(a - m) || b - a).slice(0, k);
188+
}
189+
```
190+
177191
<!-- tabs:end -->
178192

179193
<!-- solution:end -->

solution/1400-1499/1471.The k Strongest Values in an Array/README_EN.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,13 @@ Any permutation of [11,8,6,6,7] is <strong>accepted</strong>.
7676

7777
<!-- solution:start -->
7878

79-
### Solution 1
79+
### Solution 1: Sorting
80+
81+
We first sort the array $\textit{arr}$ and then find the median $m$ of the array.
82+
83+
Next, we sort the array according to the rules described in the problem, and finally return the first $k$ elements of the array.
84+
85+
The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{arr}$.
8086

8187
<!-- tabs:start -->
8288

@@ -158,6 +164,16 @@ func abs(x int) int {
158164
}
159165
```
160166

167+
#### TypeScript
168+
169+
```ts
170+
function getStrongest(arr: number[], k: number): number[] {
171+
arr.sort((a, b) => a - b);
172+
const m = arr[(arr.length - 1) >> 1];
173+
return arr.sort((a, b) => Math.abs(b - m) - Math.abs(a - m) || b - a).slice(0, k);
174+
}
175+
```
176+
161177
<!-- tabs:end -->
162178

163179
<!-- solution:end -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function getStrongest(arr: number[], k: number): number[] {
2+
arr.sort((a, b) => a - b);
3+
const m = arr[(arr.length - 1) >> 1];
4+
return arr.sort((a, b) => Math.abs(b - m) - Math.abs(a - m) || b - a).slice(0, k);
5+
}

solution/1400-1499/1472.Design Browser History/README.md

+10-2
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,17 @@ browserHistory.back(7); // 你原本在浏览 &quot;google.com
7676

7777
<!-- solution:start -->
7878

79-
### 方法一:
79+
### 方法一:双栈
8080

81-
使用两个栈模拟前进与后退操作。
81+
我们可以使用两个栈 $\textit{stk1}$ 和 $\textit{stk2}$ 分别存储浏览后退页面和前进页面。初始时 $\textit{stk1}$ 包含 $\textit{homepage}$,而 $\textit{stk2}$ 为空。
82+
83+
调用 $\text{visit}(url)$ 时,我们将 $\textit{url}$ 加入 $\textit{stk1}$,并清空 $\textit{stk2}$。时间复杂度 $O(1)$。
84+
85+
调用 $\text{back}(steps)$ 时,我们将 $\textit{stk1}$ 的栈顶元素弹出并加入 $\textit{stk2}$,重复这一操作 $steps$ 次,直到 $\textit{stk1}$ 的长度为 $1$ 或者 $steps$ 为 $0$。最后返回 $\textit{stk1}$ 的栈顶元素。时间复杂度 $O(\textit{steps})$。
86+
87+
调用 $\text{forward}(steps)$ 时,我们将 $\textit{stk2}$ 的栈顶元素弹出并加入 $\textit{stk1}$,重复这一操作 $steps$ 次,直到 $\textit{stk2}$ 为空或者 $steps$ 为 $0$。最后返回 $\textit{stk1}$ 的栈顶元素。时间复杂度 $O(\textit{steps})$。
88+
89+
空间复杂度 $O(n)$,其中 $n$ 是浏览历史记录的长度。
8290

8391
<!-- tabs:start -->
8492

solution/1400-1499/1472.Design Browser History/README_EN.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,17 @@ browserHistory.back(7); // You are in &quot;google.com&quot;,
7575

7676
<!-- solution:start -->
7777

78-
### Solution 1
78+
### Solution 1: Two Stacks
79+
80+
We can use two stacks, $\textit{stk1}$ and $\textit{stk2}$, to store the back and forward pages, respectively. Initially, $\textit{stk1}$ contains the $\textit{homepage}$, and $\textit{stk2}$ is empty.
81+
82+
When calling $\text{visit}(url)$, we add $\textit{url}$ to $\textit{stk1}$ and clear $\textit{stk2}$. The time complexity is $O(1)$.
83+
84+
When calling $\text{back}(steps)$, we pop the top element from $\textit{stk1}$ and push it to $\textit{stk2}$. We repeat this operation $steps$ times until the length of $\textit{stk1}$ is $1$ or $steps$ is $0$. Finally, we return the top element of $\textit{stk1}$. The time complexity is $O(\textit{steps})$.
85+
86+
When calling $\text{forward}(steps)$, we pop the top element from $\textit{stk2}$ and push it to $\textit{stk1}$. We repeat this operation $steps$ times until $\textit{stk2}$ is empty or $steps$ is $0$. Finally, we return the top element of $\textit{stk1}$. The time complexity is $O(\textit{steps})$.
87+
88+
The space complexity is $O(n)$, where $n$ is the length of the browsing history.
7989

8090
<!-- tabs:start -->
8191

solution/1400-1499/1473.Paint House III/README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -91,25 +91,25 @@ tags:
9191

9292
### 方法一:动态规划
9393

94-
我们定义 $f[i][j][k]$ 表示将下标 $[0,..i]$ 的房子涂上颜色,最后一个房子的颜色为 $j$,且恰好形成 $k$ 个街区的最小花费。那么答案就是 $f[m-1][j][target]$,其中 $j$ 的取值范围为 $[1,..n]$。初始时,我们判断下标为 $0$ 的房子是否已经涂色,如果未涂色,那么 $f[0][j][1] = cost[0][j - 1]$,其中 $j \in [1,..n]$。如果已经涂色,那么 $f[0][houses[0]][1] = 0$。其他的 $f[i][j][k]$ 的值都初始化为 $\infty$。
94+
我们定义 $f[i][j][k]$ 表示将下标 $[0,..i]$ 的房子涂上颜色,最后一个房子的颜色为 $j$,且恰好形成 $k$ 个街区的最小花费。那么答案就是 $f[m-1][j][\textit{target}]$,其中 $j$ 的取值范围为 $[1,..n]$。初始时,我们判断下标为 $0$ 的房子是否已经涂色,如果未涂色,那么 $f[0][j][1] = \textit{cost}[0][j - 1]$,其中 $j \in [1,..n]$。如果已经涂色,那么 $f[0][\textit{houses}[0]][1] = 0$。其他的 $f[i][j][k]$ 的值都初始化为 $\infty$。
9595

9696
接下来,我们从下标 $i=1$ 开始遍历,对于每个 $i$,我们判断下标为 $i$ 的房子是否已经涂色:
9797

98-
如果未涂色,那么我们可以将下标为 $i$ 的房子涂成颜色 $j$,我们枚举街区的数量 $k$,其中 $k \in [1,..min(target, i + 1)]$,并且枚举下标为 $i$ 的房子的前一个房子的颜色 $j_0$,其中 $j_0 \in [1,..n]$,那么我们可以得到状态转移方程:
98+
如果未涂色,那么我们可以将下标为 $i$ 的房子涂成颜色 $j$,我们枚举街区的数量 $k$,其中 $k \in [1,..\min(\textit{target}, i + 1)]$,并且枚举下标为 $i$ 的房子的前一个房子的颜色 $j_0$,其中 $j_0 \in [1,..n]$,那么我们可以得到状态转移方程:
9999

100100
$$
101-
f[i][j][k] = \min_{j_0 \in [1,..n]} \{ f[i - 1][j_0][k - (j \neq j_0)] + cost[i][j - 1] \}
101+
f[i][j][k] = \min_{j_0 \in [1,..n]} \{ f[i - 1][j_0][k - (j \neq j_0)] + \textit{cost}[i][j - 1] \}
102102
$$
103103

104-
如果已经涂色,那么我们可以将下标为 $i$ 的房子涂成颜色 $j$,我们枚举街区的数量 $k$,其中 $k \in [1,..min(target, i + 1)]$,并且枚举下标为 $i$ 的房子的前一个房子的颜色 $j_0$,其中 $j_0 \in [1,..n]$,那么我们可以得到状态转移方程:
104+
如果已经涂色,那么我们可以将下标为 $i$ 的房子涂成颜色 $j$,我们枚举街区的数量 $k$,其中 $k \in [1,..\min(\textit{target}, i + 1)]$,并且枚举下标为 $i$ 的房子的前一个房子的颜色 $j_0$,其中 $j_0 \in [1,..n]$,那么我们可以得到状态转移方程:
105105

106106
$$
107107
f[i][j][k] = \min_{j_0 \in [1,..n]} \{ f[i - 1][j_0][k - (j \neq j_0)] \}
108108
$$
109109

110-
最后,我们返回 $f[m - 1][j][target]$,其中 $j \in [1,..n]$,如果所有的 $f[m - 1][j][target]$ 的值都为 $\infty$,那么返回 $-1$。
110+
最后,我们返回 $f[m - 1][j][\textit{target}]$,其中 $j \in [1,..n]$,如果所有的 $f[m - 1][j][\textit{target}]$ 的值都为 $\infty$,那么返回 $-1$。
111111

112-
时间复杂度 $O(m \times n^2 \times target)$,空间复杂度 $O(m \times n \times target)$。其中 $m$, $n$, $target$ 分别为房子的数量,颜色的数量,街区的数量。
112+
时间复杂度 $O(m \times n^2 \times \textit{target})$,空间复杂度 $O(m \times n \times \textit{target})$。其中 $m$, $n$, $\textit{target}$ 分别为房子的数量,颜色的数量,街区的数量。
113113

114114
<!-- tabs:start -->
115115

solution/1400-1499/1473.Paint House III/README_EN.md

+22-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Cost of paint all houses (1 + 1 + 1 + 1 + 5) = 9.
5353
<strong>Input:</strong> houses = [0,2,1,2,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], m = 5, n = 2, target = 3
5454
<strong>Output:</strong> 11
5555
<strong>Explanation:</strong> Some houses are already painted, Paint the houses of this way [2,2,1,2,2]
56-
This array contains target = 3 neighborhoods, [{2,2}, {1}, {2,2}].
56+
This array contains target = 3 neighborhoods, [{2,2}, {1}, {2,2}].
5757
Cost of paint the first and last house (10 + 1) = 11.
5858
</pre>
5959

@@ -84,7 +84,27 @@ Cost of paint the first and last house (10 + 1) = 11.
8484

8585
<!-- solution:start -->
8686

87-
### Solution 1
87+
### Solution 1: Dynamic Programming
88+
89+
We define $f[i][j][k]$ to represent the minimum cost to paint houses from index $0$ to $i$, with the last house painted in color $j$, and exactly forming $k$ blocks. The answer is $f[m-1][j][\textit{target}]$, where $j$ ranges from $1$ to $n$. Initially, we check if the house at index $0$ is already painted. If it is not painted, then $f[0][j][1] = \textit{cost}[0][j - 1]$, where $j \in [1,..n]$. If it is already painted, then $f[0][\textit{houses}[0]][1] = 0$. All other values of $f[i][j][k]$ are initialized to $\infty$.
90+
91+
Next, we start iterating from index $i=1$. For each $i$, we check if the house at index $i$ is already painted:
92+
93+
If it is not painted, we can paint the house at index $i$ with color $j$. We enumerate the number of blocks $k$, where $k \in [1,..\min(\textit{target}, i + 1)]$, and enumerate the color of the previous house $j_0$, where $j_0 \in [1,..n]$. Then we can derive the state transition equation:
94+
95+
$$
96+
f[i][j][k] = \min_{j_0 \in [1,..n]} \{ f[i - 1][j_0][k - (j \neq j_0)] + \textit{cost}[i][j - 1] \}
97+
$$
98+
99+
If it is already painted, we can paint the house at index $i$ with color $j$. We enumerate the number of blocks $k$, where $k \in [1,..\min(\textit{target}, i + 1)]$, and enumerate the color of the previous house $j_0$, where $j_0 \in [1,..n]$. Then we can derive the state transition equation:
100+
101+
$$
102+
f[i][j][k] = \min_{j_0 \in [1,..n]} \{ f[i - 1][j_0][k - (j \neq j_0)] \}
103+
$$
104+
105+
Finally, we return $f[m - 1][j][\textit{target}]$, where $j \in [1,..n]$. If all values of $f[m - 1][j][\textit{target}]$ are $\infty$, then return $-1$.
106+
107+
The time complexity is $O(m \times n^2 \times \textit{target})$, and the space complexity is $O(m \times n \times \textit{target})$. Here, $m$, $n$, and $\textit{target}$ represent the number of houses, the number of colors, and the number of blocks, respectively.
88108

89109
<!-- tabs:start -->
90110

solution/1400-1499/1474.Delete N Nodes After M Nodes of a Linked List/README.md

+37-2
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ tags:
8686

8787
### 方法一:模拟
8888

89-
按照题意模拟,遍历链表,每次遍历 $m$ 个节点,然后删除 $n$ 个节点,直到链表尾部
89+
我们可以模拟整个删除过程,首先用 $\textit{pre}$ 指针指向链表头部,然后遍历链表,移动 $m - 1$ 步,如果 $\textit{pre}$ 为空,说明从当前节点开始的节点个数小于 $m$,直接返回头部;否则,用 $\textit{cur}$ 指针指向 $\textit{pre}$,然后移动 $n$ 步,如果 $\textit{cur}$ 为空,说明从 $\textit{pre}$ 开始的节点个数小于 $m + n$,直接将 $\textit{pre}$ 的 $\textit{next}$ 指向 $\text{null}$;否则,将 $\textit{pre}$ 的 $\textit{next}$ 指向 $\textit{cur}$ 的 $\textit{next}$,然后将 $\textit{pre}$ 移动到 $\textit{pre}$ 的 $\textit{next}$。继续遍历链表,直到 $\textit{pre}$ 为空,返回头部
9090

91-
时间复杂度 $O(n)$,空间复杂度 $O(1)$。
91+
时间复杂度 $O(n)$,其中 $n$ 是链表中节点的个数。空间复杂度 $O(1)$。
9292

9393
<!-- tabs:start -->
9494

@@ -222,6 +222,41 @@ func deleteNodes(head *ListNode, m int, n int) *ListNode {
222222
}
223223
```
224224

225+
#### TypeScript
226+
227+
```ts
228+
/**
229+
* Definition for singly-linked list.
230+
* class ListNode {
231+
* val: number
232+
* next: ListNode | null
233+
* constructor(val?: number, next?: ListNode | null) {
234+
* this.val = (val===undefined ? 0 : val)
235+
* this.next = (next===undefined ? null : next)
236+
* }
237+
* }
238+
*/
239+
240+
function deleteNodes(head: ListNode | null, m: number, n: number): ListNode | null {
241+
let pre = head;
242+
while (pre) {
243+
for (let i = 0; i < m - 1 && pre; ++i) {
244+
pre = pre.next;
245+
}
246+
if (!pre) {
247+
break;
248+
}
249+
let cur = pre;
250+
for (let i = 0; i < n && cur; ++i) {
251+
cur = cur.next;
252+
}
253+
pre.next = cur?.next || null;
254+
pre = pre.next;
255+
}
256+
return head;
257+
}
258+
```
259+
225260
<!-- tabs:end -->
226261

227262
<!-- solution:end -->

solution/1400-1499/1474.Delete N Nodes After M Nodes of a Linked List/README_EN.md

+40-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,11 @@ Head of the linked list after removing nodes is returned.
6767

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

70-
### Solution 1
70+
### Solution 1: Simulation
71+
72+
We can simulate the entire deletion process. First, use a pointer $\textit{pre}$ to point to the head of the linked list, then traverse the linked list, moving $m - 1$ steps. If $\textit{pre}$ is null, it means the number of nodes from the current node is less than $m$, so we directly return the head. Otherwise, use a pointer $\textit{cur}$ to point to $\textit{pre}$, then move $n$ steps. If $\textit{cur}$ is null, it means the number of nodes from $\textit{pre}$ is less than $m + n$, so we directly set the $\textit{next}$ of $\textit{pre}$ to null. Otherwise, set the $\textit{next}$ of $\textit{pre}$ to the $\textit{next}$ of $\textit{cur}$, then move $\textit{pre}$ to its $\textit{next}$. Continue traversing the linked list until $\textit{pre}$ is null, then return the head.
73+
74+
The time complexity is $O(n)$, where $n$ is the number of nodes in the linked list. The space complexity is $O(1)$.
7175

7276
<!-- tabs:start -->
7377

@@ -201,6 +205,41 @@ func deleteNodes(head *ListNode, m int, n int) *ListNode {
201205
}
202206
```
203207

208+
#### TypeScript
209+
210+
```ts
211+
/**
212+
* Definition for singly-linked list.
213+
* class ListNode {
214+
* val: number
215+
* next: ListNode | null
216+
* constructor(val?: number, next?: ListNode | null) {
217+
* this.val = (val===undefined ? 0 : val)
218+
* this.next = (next===undefined ? null : next)
219+
* }
220+
* }
221+
*/
222+
223+
function deleteNodes(head: ListNode | null, m: number, n: number): ListNode | null {
224+
let pre = head;
225+
while (pre) {
226+
for (let i = 0; i < m - 1 && pre; ++i) {
227+
pre = pre.next;
228+
}
229+
if (!pre) {
230+
break;
231+
}
232+
let cur = pre;
233+
for (let i = 0; i < n && cur; ++i) {
234+
cur = cur.next;
235+
}
236+
pre.next = cur?.next || null;
237+
pre = pre.next;
238+
}
239+
return head;
240+
}
241+
```
242+
204243
<!-- tabs:end -->
205244

206245
<!-- solution:end -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Definition for singly-linked list.
3+
* class ListNode {
4+
* val: number
5+
* next: ListNode | null
6+
* constructor(val?: number, next?: ListNode | null) {
7+
* this.val = (val===undefined ? 0 : val)
8+
* this.next = (next===undefined ? null : next)
9+
* }
10+
* }
11+
*/
12+
13+
function deleteNodes(head: ListNode | null, m: number, n: number): ListNode | null {
14+
let pre = head;
15+
while (pre) {
16+
for (let i = 0; i < m - 1 && pre; ++i) {
17+
pre = pre.next;
18+
}
19+
if (!pre) {
20+
break;
21+
}
22+
let cur = pre;
23+
for (let i = 0; i < n && cur; ++i) {
24+
cur = cur.next;
25+
}
26+
pre.next = cur?.next || null;
27+
pre = pre.next;
28+
}
29+
return head;
30+
}

0 commit comments

Comments
 (0)