Skip to content

Commit be7a64e

Browse files
authored
feat: add solutions to lc problems: No.1572,1574 (#3818)
* No.1572.Matrix Diagonal Sum * No.1574.Shortest Subarray to be Removed to Make Array Sorted
1 parent a11f78a commit be7a64e

File tree

8 files changed

+94
-106
lines changed

8 files changed

+94
-106
lines changed

solution/1500-1599/1572.Matrix Diagonal Sum/README.md

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,10 @@ tags:
7373

7474
### 方法一:逐行遍历
7575

76-
我们可以遍历矩阵的每一行 $row[i]$,对于每一行,我们可以计算出两个对角线上的元素,即 $row[i][i]$ 和 $row[i][n - i - 1]$,其中 $n$ 是矩阵的行数。如果 $i = n - i - 1$,则说明当前行的对角线上只有一个元素,否则有两个元素。我们将其加到答案中即可。
77-
76+
我们可以遍历矩阵的每一行 $\textit{row}[i]$,对于每一行,我们可以计算出两个对角线上的元素,即 $\textit{row}[i][i]$ 和 $\textit{row}[i][n - i - 1]$,其中 $n$ 是矩阵的行数。如果 $i = n - i - 1$,则说明当前行的对角线上只有一个元素,否则有两个元素。我们将其加到答案中即可。
7877
遍历完所有行后,即可得到答案。
7978

80-
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 是矩阵的行数
79+
时间复杂度 $O(n)$,其中 $n$ 是矩阵的行数。空间复杂度 $O(1)$。
8180

8281
<!-- tabs:start -->
8382

@@ -163,12 +162,15 @@ impl Solution {
163162
pub fn diagonal_sum(mat: Vec<Vec<i32>>) -> i32 {
164163
let n = mat.len();
165164
let mut ans = 0;
165+
166166
for i in 0..n {
167-
ans += mat[i][i] + mat[n - 1 - i][i];
168-
}
169-
if (n & 1) == 1 {
170-
ans -= mat[n >> 1][n >> 1];
167+
ans += mat[i][i];
168+
let j = n - i - 1;
169+
if j != i {
170+
ans += mat[i][j];
171+
}
171172
}
173+
172174
ans
173175
}
174176
}
@@ -179,37 +181,12 @@ impl Solution {
179181
```c
180182
int diagonalSum(int** mat, int matSize, int* matColSize) {
181183
int ans = 0;
182-
for (int i = 0; i < matSize; i++) {
183-
ans += mat[i][i] + mat[i][matSize - 1 - i];
184-
}
185-
if (matSize & 1) {
186-
ans -= mat[matSize >> 1][matSize >> 1];
187-
}
188-
return ans;
189-
}
190-
```
191-
192-
<!-- tabs:end -->
193-
194-
<!-- solution:end -->
195-
196-
<!-- solution:start -->
197-
198-
### 方法二
199-
200-
<!-- tabs:start -->
201-
202-
#### TypeScript
203-
204-
```ts
205-
function diagonalSum(mat: number[][]): number {
206-
const n = mat.length;
207-
let ans = 0;
208-
for (let i = 0; i < n; i++) {
209-
ans += mat[i][i] + mat[i][n - 1 - i];
210-
}
211-
if (n & 1) {
212-
ans -= mat[n >> 1][n >> 1];
184+
for (int i = 0; i < matSize; ++i) {
185+
ans += mat[i][i];
186+
int j = matSize - i - 1;
187+
if (j != i) {
188+
ans += mat[i][j];
189+
}
213190
}
214191
return ans;
215192
}

solution/1500-1599/1572.Matrix Diagonal Sum/README_EN.md

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,13 @@ Notice that element mat[1][1] = 5 is counted only once.
6767

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

70-
### Solution 1
70+
### Solution 1: Row-by-Row Traversal
71+
72+
We can traverse each row $\textit{row}[i]$ of the matrix. For each row, we calculate the elements on the two diagonals, i.e., $\textit{row}[i][i]$ and $\textit{row}[i][n - i - 1]$, where $n$ is the number of rows in the matrix. If $i = n - i - 1$, it means there is only one element on the diagonals of the current row; otherwise, there are two elements. We add these elements to the answer.
73+
74+
After traversing all rows, we get the answer.
75+
76+
The time complexity is $O(n)$, where $n$ is the number of rows in the matrix. The space complexity is $O(1)$.
7177

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

@@ -153,12 +159,15 @@ impl Solution {
153159
pub fn diagonal_sum(mat: Vec<Vec<i32>>) -> i32 {
154160
let n = mat.len();
155161
let mut ans = 0;
162+
156163
for i in 0..n {
157-
ans += mat[i][i] + mat[n - 1 - i][i];
158-
}
159-
if (n & 1) == 1 {
160-
ans -= mat[n >> 1][n >> 1];
164+
ans += mat[i][i];
165+
let j = n - i - 1;
166+
if j != i {
167+
ans += mat[i][j];
168+
}
161169
}
170+
162171
ans
163172
}
164173
}
@@ -169,37 +178,12 @@ impl Solution {
169178
```c
170179
int diagonalSum(int** mat, int matSize, int* matColSize) {
171180
int ans = 0;
172-
for (int i = 0; i < matSize; i++) {
173-
ans += mat[i][i] + mat[i][matSize - 1 - i];
174-
}
175-
if (matSize & 1) {
176-
ans -= mat[matSize >> 1][matSize >> 1];
177-
}
178-
return ans;
179-
}
180-
```
181-
182-
<!-- tabs:end -->
183-
184-
<!-- solution:end -->
185-
186-
<!-- solution:start -->
187-
188-
### Solution 2
189-
190-
<!-- tabs:start -->
191-
192-
#### TypeScript
193-
194-
```ts
195-
function diagonalSum(mat: number[][]): number {
196-
const n = mat.length;
197-
let ans = 0;
198-
for (let i = 0; i < n; i++) {
199-
ans += mat[i][i] + mat[i][n - 1 - i];
200-
}
201-
if (n & 1) {
202-
ans -= mat[n >> 1][n >> 1];
181+
for (int i = 0; i < matSize; ++i) {
182+
ans += mat[i][i];
183+
int j = matSize - i - 1;
184+
if (j != i) {
185+
ans += mat[i][j];
186+
}
203187
}
204188
return ans;
205189
}
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
int diagonalSum(int** mat, int matSize, int* matColSize) {
22
int ans = 0;
3-
for (int i = 0; i < matSize; i++) {
4-
ans += mat[i][i] + mat[i][matSize - 1 - i];
5-
}
6-
if (matSize & 1) {
7-
ans -= mat[matSize >> 1][matSize >> 1];
3+
for (int i = 0; i < matSize; ++i) {
4+
ans += mat[i][i];
5+
int j = matSize - i - 1;
6+
if (j != i) {
7+
ans += mat[i][j];
8+
}
89
}
910
return ans;
10-
}
11+
}

solution/1500-1599/1572.Matrix Diagonal Sum/Solution.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ impl Solution {
22
pub fn diagonal_sum(mat: Vec<Vec<i32>>) -> i32 {
33
let n = mat.len();
44
let mut ans = 0;
5+
56
for i in 0..n {
6-
ans += mat[i][i] + mat[n - 1 - i][i];
7-
}
8-
if (n & 1) == 1 {
9-
ans -= mat[n >> 1][n >> 1];
7+
ans += mat[i][i];
8+
let j = n - i - 1;
9+
if j != i {
10+
ans += mat[i][j];
11+
}
1012
}
13+
1114
ans
1215
}
1316
}

solution/1500-1599/1572.Matrix Diagonal Sum/Solution2.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

solution/1500-1599/1573.Number of Ways to Split a String/README_EN.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,21 @@ tags:
6868

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

71-
### Solution 1
71+
### Solution 1: Counting
72+
73+
First, we traverse the string $s$ and count the number of characters $1$, denoted as $cnt$. If $cnt$ cannot be divided by $3$, then it is impossible to split the string, so we directly return $0$. If $cnt$ is $0$, it means there are no characters $1$ in the string. We can choose any two positions out of $n-1$ positions to split the string into three substrings, so the number of ways is $C_{n-1}^2$.
74+
75+
If $cnt \gt 0$, we update $cnt$ to $\frac{cnt}{3}$, which is the number of characters $1$ in each substring.
76+
77+
Next, we find the minimum index of the right boundary of the first substring, denoted as $i_1$, and the maximum index of the right boundary of the first substring (exclusive), denoted as $i_2$. Similarly, we find the minimum index of the right boundary of the second substring, denoted as $j_1$, and the maximum index of the right boundary of the second substring (exclusive), denoted as $j_2$. Then the number of ways is $(i_2 - i_1) \times (j_2 - j_1)$.
78+
79+
Note that the answer may be very large, so we need to take the modulo $10^9+7$.
80+
81+
The time complexity is $O(n)$, and the space complexity is $O(1)$. Here, $n$ is the length of the string $s$.
82+
83+
Similar problems:
84+
85+
- [927. Three Equal Parts](https://github.com/doocs/leetcode/blob/main/solution/0900-0999/0927.Three%20Equal%20Parts/README_EN.md)
7286

7387
<!-- tabs:start -->
7488

solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ tags:
7878

7979
### 方法一:双指针 + 二分查找
8080

81-
我们先找出数组的最长非递减前缀和最长非递减后缀,分别记为 $nums[0..i]$ 和 $nums[j..n-1]$。
81+
我们先找出数组的最长非递减前缀和最长非递减后缀,分别记为 $\textit{nums}[0..i]$ 和 $\textit{nums}[j..n-1]$。
8282

8383
如果 $i \geq j$,说明数组本身就是非递减的,返回 $0$。
8484

85-
否则,我们可以选择删除右侧后缀,也可以选择删除左侧前缀,因此初始时答案为 $min(n - i - 1, j)$。
85+
否则,我们可以选择删除右侧后缀,也可以选择删除左侧前缀,因此初始时答案为 $\min(n - i - 1, j)$。
8686

87-
接下来,我们枚举左侧前缀的最右端点 $l$,对于每个 $l$,我们可以通过二分查找,在 $nums[j..n-1]$ 中找到第一个大于等于 $nums[l]$ 的位置,记为 $r$,此时我们可以删除 $nums[l+1..r-1]$,并且更新答案 $ans = min(ans, r - l - 1)$。继续枚举 $l$,最终得到答案。
87+
接下来,我们枚举左侧前缀的最右端点 $l$,对于每个 $l$,我们可以通过二分查找,在 $\textit{nums}[j..n-1]$ 中找到第一个大于等于 $\textit{nums}[l]$ 的位置,记为 $r$,此时我们可以删除 $\textit{nums}[l+1..r-1]$,并且更新答案 $\textit{ans} = \min(\textit{ans}, r - l - 1)$。继续枚举 $l$,最终得到答案。
8888

89-
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(1)$。其中 $n$ 为数组长度
89+
时间复杂度 $O(n \times \log n)$,其中 $n$ 为数组长度。空间复杂度 $O(1)$。
9090

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

@@ -208,15 +208,15 @@ func findLengthOfShortestSubarray(arr []int) int {
208208

209209
### 方法二:双指针
210210

211-
与方法一类似,我们先找出数组的最长非递减前缀和最长非递减后缀,分别记为 $nums[0..i]$ 和 $nums[j..n-1]$。
211+
与方法一类似,我们先找出数组的最长非递减前缀和最长非递减后缀,分别记为 $\textit{nums}[0..i]$ 和 $\textit{nums}[j..n-1]$。
212212

213213
如果 $i \geq j$,说明数组本身就是非递减的,返回 $0$。
214214

215-
否则,我们可以选择删除右侧后缀,也可以选择删除左侧前缀,因此初始时答案为 $min(n - i - 1, j)$。
215+
否则,我们可以选择删除右侧后缀,也可以选择删除左侧前缀,因此初始时答案为 $\min(n - i - 1, j)$。
216216

217-
接下来,我们枚举左侧前缀的最右端点 $l$,对于每个 $l$,我们直接利用双指针找到第一个大于等于 $nums[l]$ 的位置,记为 $r$,此时我们可以删除 $nums[l+1..r-1]$,并且更新答案 $ans = min(ans, r - l - 1)$。继续枚举 $l$,最终得到答案。
217+
接下来,我们枚举左侧前缀的最右端点 $l$,对于每个 $l$,我们直接利用双指针找到第一个大于等于 $\textit{nums}[l]$ 的位置,记为 $r$,此时我们可以删除 $\textit{nums}[l+1..r-1]$,并且更新答案 $\textit{ans} = \min(\textit{ans}, r - l - 1)$。继续枚举 $l$,最终得到答案。
218218

219-
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组长度
219+
时间复杂度 $O(n)$,其中 $n$ 为数组长度。空间复杂度 $O(1)$。
220220

221221
<!-- tabs:start -->
222222

solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README_EN.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,17 @@ Another correct solution is to remove the subarray [3,10,4].
6868

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

71-
### Solution 1
71+
### Solution 1: Two Pointers + Binary Search
72+
73+
First, we find the longest non-decreasing prefix and the longest non-decreasing suffix of the array, denoted as $\textit{nums}[0..i]$ and $\textit{nums}[j..n-1]$, respectively.
74+
75+
If $i \geq j$, it means the array is already non-decreasing, so we return $0$.
76+
77+
Otherwise, we can choose to delete the right suffix or the left prefix. Therefore, initially, the answer is $\min(n - i - 1, j)$.
78+
79+
Next, we enumerate the right endpoint $l$ of the left prefix. For each $l$, we can use binary search to find the first position greater than or equal to $\textit{nums}[l]$ in $\textit{nums}[j..n-1]$, denoted as $r$. At this point, we can delete $\textit{nums}[l+1..r-1]$ and update the answer $\textit{ans} = \min(\textit{ans}, r - l - 1)$. Continue enumerating $l$ to get the final answer.
80+
81+
The time complexity is $O(n \times \log n)$, where $n$ is the length of the array. The space complexity is $O(1)$.
7282

7383
<!-- tabs:start -->
7484

@@ -188,7 +198,17 @@ func findLengthOfShortestSubarray(arr []int) int {
188198

189199
<!-- solution:start -->
190200

191-
### Solution 2
201+
### Solution 2: Two Pointers
202+
203+
Similar to Solution 1, we first find the longest non-decreasing prefix and the longest non-decreasing suffix of the array, denoted as $\textit{nums}[0..i]$ and $\textit{nums}[j..n-1]$, respectively.
204+
205+
If $i \geq j$, it means the array is already non-decreasing, so we return $0$.
206+
207+
Otherwise, we can choose to delete the right suffix or the left prefix. Therefore, initially, the answer is $\min(n - i - 1, j)$.
208+
209+
Next, we enumerate the right endpoint $l$ of the left prefix. For each $l$, we directly use two pointers to find the first position greater than or equal to $\textit{nums}[l]$ in $\textit{nums}[j..n-1]$, denoted as $r$. At this point, we can delete $\textit{nums}[l+1..r-1]$ and update the answer $\textit{ans} = \min(\textit{ans}, r - l - 1)$. Continue enumerating $l$ to get the final answer.
210+
211+
The time complexity is $O(n)$, where $n$ is the length of the array. The space complexity is $O(1)$.
192212

193213
<!-- tabs:start -->
194214

0 commit comments

Comments
 (0)