Skip to content

feat: add solutions to lc problems: No.1572,1574 #3818

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 15 additions & 38 deletions solution/1500-1599/1572.Matrix Diagonal Sum/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,10 @@ tags:

### 方法一:逐行遍历

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

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

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

<!-- tabs:start -->

Expand Down Expand Up @@ -163,12 +162,15 @@ impl Solution {
pub fn diagonal_sum(mat: Vec<Vec<i32>>) -> i32 {
let n = mat.len();
let mut ans = 0;

for i in 0..n {
ans += mat[i][i] + mat[n - 1 - i][i];
}
if (n & 1) == 1 {
ans -= mat[n >> 1][n >> 1];
ans += mat[i][i];
let j = n - i - 1;
if j != i {
ans += mat[i][j];
}
}

ans
}
}
Expand All @@ -179,37 +181,12 @@ impl Solution {
```c
int diagonalSum(int** mat, int matSize, int* matColSize) {
int ans = 0;
for (int i = 0; i < matSize; i++) {
ans += mat[i][i] + mat[i][matSize - 1 - i];
}
if (matSize & 1) {
ans -= mat[matSize >> 1][matSize >> 1];
}
return ans;
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- solution:start -->

### 方法二

<!-- tabs:start -->

#### TypeScript

```ts
function diagonalSum(mat: number[][]): number {
const n = mat.length;
let ans = 0;
for (let i = 0; i < n; i++) {
ans += mat[i][i] + mat[i][n - 1 - i];
}
if (n & 1) {
ans -= mat[n >> 1][n >> 1];
for (int i = 0; i < matSize; ++i) {
ans += mat[i][i];
int j = matSize - i - 1;
if (j != i) {
ans += mat[i][j];
}
}
return ans;
}
Expand Down
56 changes: 20 additions & 36 deletions solution/1500-1599/1572.Matrix Diagonal Sum/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@ Notice that element mat[1][1] = 5 is counted only once.

<!-- solution:start -->

### Solution 1
### Solution 1: Row-by-Row Traversal

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.

After traversing all rows, we get the answer.

The time complexity is $O(n)$, where $n$ is the number of rows in the matrix. The space complexity is $O(1)$.

<!-- tabs:start -->

Expand Down Expand Up @@ -153,12 +159,15 @@ impl Solution {
pub fn diagonal_sum(mat: Vec<Vec<i32>>) -> i32 {
let n = mat.len();
let mut ans = 0;

for i in 0..n {
ans += mat[i][i] + mat[n - 1 - i][i];
}
if (n & 1) == 1 {
ans -= mat[n >> 1][n >> 1];
ans += mat[i][i];
let j = n - i - 1;
if j != i {
ans += mat[i][j];
}
}

ans
}
}
Expand All @@ -169,37 +178,12 @@ impl Solution {
```c
int diagonalSum(int** mat, int matSize, int* matColSize) {
int ans = 0;
for (int i = 0; i < matSize; i++) {
ans += mat[i][i] + mat[i][matSize - 1 - i];
}
if (matSize & 1) {
ans -= mat[matSize >> 1][matSize >> 1];
}
return ans;
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- solution:start -->

### Solution 2

<!-- tabs:start -->

#### TypeScript

```ts
function diagonalSum(mat: number[][]): number {
const n = mat.length;
let ans = 0;
for (let i = 0; i < n; i++) {
ans += mat[i][i] + mat[i][n - 1 - i];
}
if (n & 1) {
ans -= mat[n >> 1][n >> 1];
for (int i = 0; i < matSize; ++i) {
ans += mat[i][i];
int j = matSize - i - 1;
if (j != i) {
ans += mat[i][j];
}
}
return ans;
}
Expand Down
13 changes: 7 additions & 6 deletions solution/1500-1599/1572.Matrix Diagonal Sum/Solution.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
int diagonalSum(int** mat, int matSize, int* matColSize) {
int ans = 0;
for (int i = 0; i < matSize; i++) {
ans += mat[i][i] + mat[i][matSize - 1 - i];
}
if (matSize & 1) {
ans -= mat[matSize >> 1][matSize >> 1];
for (int i = 0; i < matSize; ++i) {
ans += mat[i][i];
int j = matSize - i - 1;
if (j != i) {
ans += mat[i][j];
}
}
return ans;
}
}
11 changes: 7 additions & 4 deletions solution/1500-1599/1572.Matrix Diagonal Sum/Solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ impl Solution {
pub fn diagonal_sum(mat: Vec<Vec<i32>>) -> i32 {
let n = mat.len();
let mut ans = 0;

for i in 0..n {
ans += mat[i][i] + mat[n - 1 - i][i];
}
if (n & 1) == 1 {
ans -= mat[n >> 1][n >> 1];
ans += mat[i][i];
let j = n - i - 1;
if j != i {
ans += mat[i][j];
}
}

ans
}
}
11 changes: 0 additions & 11 deletions solution/1500-1599/1572.Matrix Diagonal Sum/Solution2.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,21 @@ tags:

<!-- solution:start -->

### Solution 1
### Solution 1: Counting

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$.

If $cnt \gt 0$, we update $cnt$ to $\frac{cnt}{3}$, which is the number of characters $1$ in each substring.

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)$.

Note that the answer may be very large, so we need to take the modulo $10^9+7$.

The time complexity is $O(n)$, and the space complexity is $O(1)$. Here, $n$ is the length of the string $s$.

Similar problems:

- [927. Three Equal Parts](https://github.com/doocs/leetcode/blob/main/solution/0900-0999/0927.Three%20Equal%20Parts/README_EN.md)

<!-- tabs:start -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ tags:

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

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

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

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

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

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

<!-- tabs:start -->

Expand Down Expand Up @@ -208,15 +208,15 @@ func findLengthOfShortestSubarray(arr []int) int {

### 方法二:双指针

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

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

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

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

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

<!-- tabs:start -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,17 @@ Another correct solution is to remove the subarray [3,10,4].

<!-- solution:start -->

### Solution 1
### Solution 1: Two Pointers + Binary Search

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.

If $i \geq j$, it means the array is already non-decreasing, so we return $0$.

Otherwise, we can choose to delete the right suffix or the left prefix. Therefore, initially, the answer is $\min(n - i - 1, j)$.

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.

The time complexity is $O(n \times \log n)$, where $n$ is the length of the array. The space complexity is $O(1)$.

<!-- tabs:start -->

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

<!-- solution:start -->

### Solution 2
### Solution 2: Two Pointers

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.

If $i \geq j$, it means the array is already non-decreasing, so we return $0$.

Otherwise, we can choose to delete the right suffix or the left prefix. Therefore, initially, the answer is $\min(n - i - 1, j)$.

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.

The time complexity is $O(n)$, where $n$ is the length of the array. The space complexity is $O(1)$.

<!-- tabs:start -->

Expand Down
Loading