diff --git a/solution/1500-1599/1572.Matrix Diagonal Sum/README.md b/solution/1500-1599/1572.Matrix Diagonal Sum/README.md index a8d710d4e5073..1b8182dd2afea 100644 --- a/solution/1500-1599/1572.Matrix Diagonal Sum/README.md +++ b/solution/1500-1599/1572.Matrix Diagonal Sum/README.md @@ -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)$。 @@ -163,12 +162,15 @@ impl Solution { pub fn diagonal_sum(mat: Vec>) -> 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 } } @@ -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; -} -``` - - - - - - - -### 方法二 - - - -#### 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; } diff --git a/solution/1500-1599/1572.Matrix Diagonal Sum/README_EN.md b/solution/1500-1599/1572.Matrix Diagonal Sum/README_EN.md index 1c8c7591c7143..c8ba2dcc38bc3 100644 --- a/solution/1500-1599/1572.Matrix Diagonal Sum/README_EN.md +++ b/solution/1500-1599/1572.Matrix Diagonal Sum/README_EN.md @@ -67,7 +67,13 @@ Notice that element mat[1][1] = 5 is counted only once. -### 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)$. @@ -153,12 +159,15 @@ impl Solution { pub fn diagonal_sum(mat: Vec>) -> 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 } } @@ -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; -} -``` - - - - - - - -### Solution 2 - - - -#### 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; } diff --git a/solution/1500-1599/1572.Matrix Diagonal Sum/Solution.c b/solution/1500-1599/1572.Matrix Diagonal Sum/Solution.c index 0e490859aa992..fc34f743ae31f 100644 --- a/solution/1500-1599/1572.Matrix Diagonal Sum/Solution.c +++ b/solution/1500-1599/1572.Matrix Diagonal Sum/Solution.c @@ -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; -} \ No newline at end of file +} diff --git a/solution/1500-1599/1572.Matrix Diagonal Sum/Solution.rs b/solution/1500-1599/1572.Matrix Diagonal Sum/Solution.rs index 4e78351623dc2..f28484c58d18b 100644 --- a/solution/1500-1599/1572.Matrix Diagonal Sum/Solution.rs +++ b/solution/1500-1599/1572.Matrix Diagonal Sum/Solution.rs @@ -2,12 +2,15 @@ impl Solution { pub fn diagonal_sum(mat: Vec>) -> 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 } } diff --git a/solution/1500-1599/1572.Matrix Diagonal Sum/Solution2.ts b/solution/1500-1599/1572.Matrix Diagonal Sum/Solution2.ts deleted file mode 100644 index e870aa932ff9f..0000000000000 --- a/solution/1500-1599/1572.Matrix Diagonal Sum/Solution2.ts +++ /dev/null @@ -1,11 +0,0 @@ -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]; - } - return ans; -} diff --git a/solution/1500-1599/1573.Number of Ways to Split a String/README_EN.md b/solution/1500-1599/1573.Number of Ways to Split a String/README_EN.md index 3daa1af238ca4..759a3753ca6cc 100644 --- a/solution/1500-1599/1573.Number of Ways to Split a String/README_EN.md +++ b/solution/1500-1599/1573.Number of Ways to Split a String/README_EN.md @@ -68,7 +68,21 @@ tags: -### 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) diff --git a/solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README.md b/solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README.md index 870a11b20fb03..913bb35266bdc 100644 --- a/solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README.md +++ b/solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README.md @@ -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)$。 @@ -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)$。 diff --git a/solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README_EN.md b/solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README_EN.md index 20605036e7851..7636c5d6dac99 100644 --- a/solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README_EN.md +++ b/solution/1500-1599/1574.Shortest Subarray to be Removed to Make Array Sorted/README_EN.md @@ -68,7 +68,17 @@ Another correct solution is to remove the subarray [3,10,4]. -### 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)$. @@ -188,7 +198,17 @@ func findLengthOfShortestSubarray(arr []int) int { -### 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)$.