From 73626d9e02f8a19d9558961a1b3937ac8b59c577 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Wed, 24 Jul 2024 16:46:07 +0800 Subject: [PATCH] feat: add solutions to lc problems: No.0541,0542 --- .../0541.Reverse String II/README.md | 58 ++++++++++----- .../0541.Reverse String II/README_EN.md | 58 ++++++++++----- .../0541.Reverse String II/Solution.cpp | 3 +- .../0541.Reverse String II/Solution.go | 11 +-- .../0541.Reverse String II/Solution.java | 15 ++-- .../0541.Reverse String II/Solution.py | 8 +-- .../0541.Reverse String II/Solution.ts | 10 +++ solution/0500-0599/0542.01 Matrix/README.md | 70 +++++++++---------- .../0500-0599/0542.01 Matrix/README_EN.md | 70 +++++++++---------- solution/0500-0599/0542.01 Matrix/Solution.rs | 53 ++++++-------- solution/0500-0599/0542.01 Matrix/Solution.ts | 3 +- 11 files changed, 198 insertions(+), 161 deletions(-) create mode 100644 solution/0500-0599/0541.Reverse String II/Solution.ts diff --git a/solution/0500-0599/0541.Reverse String II/README.md b/solution/0500-0599/0541.Reverse String II/README.md index a6a3dfbada4da..34e9a41e10c2a 100644 --- a/solution/0500-0599/0541.Reverse String II/README.md +++ b/solution/0500-0599/0541.Reverse String II/README.md @@ -56,7 +56,11 @@ tags: -### 方法一 +### 方法一:双指针 + +我们可以遍历字符串 $\textit{s}$,每次遍历 $\textit{2k}$ 个字符,然后利用双指针技巧,对这 $\textit{2k}$ 个字符中的前 $\textit{k}$ 个字符进行反转。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $\textit{s}$ 的长度。 @@ -65,10 +69,10 @@ tags: ```python class Solution: def reverseStr(self, s: str, k: int) -> str: - t = list(s) - for i in range(0, len(t), k << 1): - t[i : i + k] = reversed(t[i : i + k]) - return ''.join(t) + cs = list(s) + for i in range(0, len(cs), 2 * k): + cs[i : i + k] = reversed(cs[i : i + k]) + return "".join(cs) ``` #### Java @@ -76,15 +80,16 @@ class Solution: ```java class Solution { public String reverseStr(String s, int k) { - char[] chars = s.toCharArray(); - for (int i = 0; i < chars.length; i += (k << 1)) { - for (int st = i, ed = Math.min(chars.length - 1, i + k - 1); st < ed; ++st, --ed) { - char t = chars[st]; - chars[st] = chars[ed]; - chars[ed] = t; + char[] cs = s.toCharArray(); + int n = cs.length; + for (int i = 0; i < n; i += k * 2) { + for (int l = i, r = Math.min(i + k - 1, n - 1); l < r; ++l, --r) { + char t = cs[l]; + cs[l] = cs[r]; + cs[r] = t; } } - return new String(chars); + return new String(cs); } } ``` @@ -95,7 +100,8 @@ class Solution { class Solution { public: string reverseStr(string s, int k) { - for (int i = 0, n = s.size(); i < n; i += (k << 1)) { + int n = s.size(); + for (int i = 0; i < n; i += 2 * k) { reverse(s.begin() + i, s.begin() + min(i + k, n)); } return s; @@ -107,13 +113,29 @@ public: ```go func reverseStr(s string, k int) string { - t := []byte(s) - for i := 0; i < len(t); i += (k << 1) { - for st, ed := i, min(i+k-1, len(t)-1); st < ed; st, ed = st+1, ed-1 { - t[st], t[ed] = t[ed], t[st] + cs := []byte(s) + n := len(cs) + for i := 0; i < n; i += 2 * k { + for l, r := i, min(i+k-1, n-1); l < r; l, r = l+1, r-1 { + cs[l], cs[r] = cs[r], cs[l] } } - return string(t) + return string(cs) +} +``` + +#### TypeScript + +```ts +function reverseStr(s: string, k: number): string { + const n = s.length; + const cs = s.split(''); + for (let i = 0; i < n; i += 2 * k) { + for (let l = i, r = Math.min(i + k - 1, n - 1); l < r; l++, r--) { + [cs[l], cs[r]] = [cs[r], cs[l]]; + } + } + return cs.join(''); } ``` diff --git a/solution/0500-0599/0541.Reverse String II/README_EN.md b/solution/0500-0599/0541.Reverse String II/README_EN.md index 5923f43e1fe5b..4570c4d6afaec 100644 --- a/solution/0500-0599/0541.Reverse String II/README_EN.md +++ b/solution/0500-0599/0541.Reverse String II/README_EN.md @@ -44,7 +44,11 @@ tags: -### Solution 1 +### Solution 1: Two Pointers + +We can traverse the string $\textit{s}$, iterating over every $\textit{2k}$ characters, and then use the two-pointer technique to reverse the first $\textit{k}$ characters among these $\textit{2k}$ characters. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string $\textit{s}$. @@ -53,10 +57,10 @@ tags: ```python class Solution: def reverseStr(self, s: str, k: int) -> str: - t = list(s) - for i in range(0, len(t), k << 1): - t[i : i + k] = reversed(t[i : i + k]) - return ''.join(t) + cs = list(s) + for i in range(0, len(cs), 2 * k): + cs[i : i + k] = reversed(cs[i : i + k]) + return "".join(cs) ``` #### Java @@ -64,15 +68,16 @@ class Solution: ```java class Solution { public String reverseStr(String s, int k) { - char[] chars = s.toCharArray(); - for (int i = 0; i < chars.length; i += (k << 1)) { - for (int st = i, ed = Math.min(chars.length - 1, i + k - 1); st < ed; ++st, --ed) { - char t = chars[st]; - chars[st] = chars[ed]; - chars[ed] = t; + char[] cs = s.toCharArray(); + int n = cs.length; + for (int i = 0; i < n; i += k * 2) { + for (int l = i, r = Math.min(i + k - 1, n - 1); l < r; ++l, --r) { + char t = cs[l]; + cs[l] = cs[r]; + cs[r] = t; } } - return new String(chars); + return new String(cs); } } ``` @@ -83,7 +88,8 @@ class Solution { class Solution { public: string reverseStr(string s, int k) { - for (int i = 0, n = s.size(); i < n; i += (k << 1)) { + int n = s.size(); + for (int i = 0; i < n; i += 2 * k) { reverse(s.begin() + i, s.begin() + min(i + k, n)); } return s; @@ -95,13 +101,29 @@ public: ```go func reverseStr(s string, k int) string { - t := []byte(s) - for i := 0; i < len(t); i += (k << 1) { - for st, ed := i, min(i+k-1, len(t)-1); st < ed; st, ed = st+1, ed-1 { - t[st], t[ed] = t[ed], t[st] + cs := []byte(s) + n := len(cs) + for i := 0; i < n; i += 2 * k { + for l, r := i, min(i+k-1, n-1); l < r; l, r = l+1, r-1 { + cs[l], cs[r] = cs[r], cs[l] } } - return string(t) + return string(cs) +} +``` + +#### TypeScript + +```ts +function reverseStr(s: string, k: number): string { + const n = s.length; + const cs = s.split(''); + for (let i = 0; i < n; i += 2 * k) { + for (let l = i, r = Math.min(i + k - 1, n - 1); l < r; l++, r--) { + [cs[l], cs[r]] = [cs[r], cs[l]]; + } + } + return cs.join(''); } ``` diff --git a/solution/0500-0599/0541.Reverse String II/Solution.cpp b/solution/0500-0599/0541.Reverse String II/Solution.cpp index 528788dee6aad..fb9bca75b1a6e 100644 --- a/solution/0500-0599/0541.Reverse String II/Solution.cpp +++ b/solution/0500-0599/0541.Reverse String II/Solution.cpp @@ -1,7 +1,8 @@ class Solution { public: string reverseStr(string s, int k) { - for (int i = 0, n = s.size(); i < n; i += (k << 1)) { + int n = s.size(); + for (int i = 0; i < n; i += 2 * k) { reverse(s.begin() + i, s.begin() + min(i + k, n)); } return s; diff --git a/solution/0500-0599/0541.Reverse String II/Solution.go b/solution/0500-0599/0541.Reverse String II/Solution.go index 937f6a2ec1713..7d3e1ae5e2b55 100644 --- a/solution/0500-0599/0541.Reverse String II/Solution.go +++ b/solution/0500-0599/0541.Reverse String II/Solution.go @@ -1,9 +1,10 @@ func reverseStr(s string, k int) string { - t := []byte(s) - for i := 0; i < len(t); i += (k << 1) { - for st, ed := i, min(i+k-1, len(t)-1); st < ed; st, ed = st+1, ed-1 { - t[st], t[ed] = t[ed], t[st] + cs := []byte(s) + n := len(cs) + for i := 0; i < n; i += 2 * k { + for l, r := i, min(i+k-1, n-1); l < r; l, r = l+1, r-1 { + cs[l], cs[r] = cs[r], cs[l] } } - return string(t) + return string(cs) } \ No newline at end of file diff --git a/solution/0500-0599/0541.Reverse String II/Solution.java b/solution/0500-0599/0541.Reverse String II/Solution.java index 743b7105f6191..4d5d022938e9a 100644 --- a/solution/0500-0599/0541.Reverse String II/Solution.java +++ b/solution/0500-0599/0541.Reverse String II/Solution.java @@ -1,13 +1,14 @@ class Solution { public String reverseStr(String s, int k) { - char[] chars = s.toCharArray(); - for (int i = 0; i < chars.length; i += (k << 1)) { - for (int st = i, ed = Math.min(chars.length - 1, i + k - 1); st < ed; ++st, --ed) { - char t = chars[st]; - chars[st] = chars[ed]; - chars[ed] = t; + char[] cs = s.toCharArray(); + int n = cs.length; + for (int i = 0; i < n; i += k * 2) { + for (int l = i, r = Math.min(i + k - 1, n - 1); l < r; ++l, --r) { + char t = cs[l]; + cs[l] = cs[r]; + cs[r] = t; } } - return new String(chars); + return new String(cs); } } \ No newline at end of file diff --git a/solution/0500-0599/0541.Reverse String II/Solution.py b/solution/0500-0599/0541.Reverse String II/Solution.py index 3a7d74c5c8372..2487b7a841e07 100644 --- a/solution/0500-0599/0541.Reverse String II/Solution.py +++ b/solution/0500-0599/0541.Reverse String II/Solution.py @@ -1,6 +1,6 @@ class Solution: def reverseStr(self, s: str, k: int) -> str: - t = list(s) - for i in range(0, len(t), k << 1): - t[i : i + k] = reversed(t[i : i + k]) - return ''.join(t) + cs = list(s) + for i in range(0, len(cs), 2 * k): + cs[i : i + k] = reversed(cs[i : i + k]) + return "".join(cs) diff --git a/solution/0500-0599/0541.Reverse String II/Solution.ts b/solution/0500-0599/0541.Reverse String II/Solution.ts new file mode 100644 index 0000000000000..55ebb15a46121 --- /dev/null +++ b/solution/0500-0599/0541.Reverse String II/Solution.ts @@ -0,0 +1,10 @@ +function reverseStr(s: string, k: number): string { + const n = s.length; + const cs = s.split(''); + for (let i = 0; i < n; i += 2 * k) { + for (let l = i, r = Math.min(i + k - 1, n - 1); l < r; l++, r--) { + [cs[l], cs[r]] = [cs[r], cs[l]]; + } + } + return cs.join(''); +} diff --git a/solution/0500-0599/0542.01 Matrix/README.md b/solution/0500-0599/0542.01 Matrix/README.md index 1af062da84d4e..23329b7a9a4c6 100644 --- a/solution/0500-0599/0542.01 Matrix/README.md +++ b/solution/0500-0599/0542.01 Matrix/README.md @@ -62,11 +62,17 @@ tags: -### 方法一:多源 BFS +### 方法一:BFS -初始化结果矩阵 ans,所有 0 的距离为 0,所以 1 的距离为 -1。初始化队列 q 存储 BFS 需要检查的位置,并将所有 0 的位置入队。 +我们创建一个大小和 $\textit{mat}$ 一样的矩阵 $\textit{ans}$,并将所有的元素初始化为 $-1$。 -循环弹出队列 q 的元素 `p(i, j)`,检查邻居四个点。对于邻居 `(x, y)`,如果 `ans[x][y] = -1`,则更新 `ans[x][y] = ans[i][j] + 1`。同时将 `(x, y)` 入队。 +然后我们遍历 $\textit{mat}$,将所有的 $0$ 元素的坐标 $(i, j)$ 加入队列 $\textit{q}$,并将 $\textit{ans}[i][j]$ 设为 $0$。 + +接下来,我们使用广度优先搜索,从队列中取出一个元素 $(i, j)$,并遍历其四个方向,如果该方向的元素 $(x, y)$ 满足 $0 \leq x < m$, $0 \leq y < n$ 且 $\textit{ans}[x][y] = -1$,则将 $\textit{ans}[x][y]$ 设为 $\textit{ans}[i][j] + 1$,并将 $(x, y)$ 加入队列 $\textit{q}$。 + +最后返回 $\textit{ans}$。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别为矩阵 $\textit{mat}$ 的行数和列数。 @@ -219,8 +225,7 @@ function updateMatrix(mat: number[][]): number[][] { } } const dirs: number[] = [-1, 0, 1, 0, -1]; - while (q.length) { - const [i, j] = q.shift()!; + for (const [i, j] of q) { for (let k = 0; k < 4; ++k) { const [x, y] = [i + dirs[k], j + dirs[k + 1]]; if (x >= 0 && x < m && y >= 0 && y < n && ans[x][y] === -1) { @@ -239,49 +244,38 @@ function updateMatrix(mat: number[][]): number[][] { use std::collections::VecDeque; impl Solution { - #[allow(dead_code)] pub fn update_matrix(mat: Vec>) -> Vec> { - let n: usize = mat.len(); - let m: usize = mat[0].len(); - let mut ret_vec: Vec> = vec![vec![-1; m]; n]; - // The inner tuple is of - let mut the_q: VecDeque<(usize, usize)> = VecDeque::new(); - let traverse_vec: Vec<(i32, i32)> = vec![(-1, 0), (1, 0), (0, 1), (0, -1)]; - - // Initialize the queue - for i in 0..n { - for j in 0..m { + let m = mat.len(); + let n = mat[0].len(); + let mut ans = vec![vec![-1; n]; m]; + let mut q = VecDeque::new(); + + for i in 0..m { + for j in 0..n { if mat[i][j] == 0 { - // For the zero cell, enqueue at first - the_q.push_back((i, j)); - // Set to 0 in return vector - ret_vec[i][j] = 0; + q.push_back((i, j)); + ans[i][j] = 0; } } } - while !the_q.is_empty() { - let (x, y) = the_q.front().unwrap().clone(); - the_q.pop_front(); - for pair in &traverse_vec { - let cur_x = pair.0 + (x as i32); - let cur_y = pair.1 + (y as i32); - if Solution::check_bounds(cur_x, cur_y, n as i32, m as i32) - && ret_vec[cur_x as usize][cur_y as usize] == -1 - { - // The current cell has not be updated yet, and is also in bound - ret_vec[cur_x as usize][cur_y as usize] = ret_vec[x][y] + 1; - the_q.push_back((cur_x as usize, cur_y as usize)); + let dirs = [-1, 0, 1, 0, -1]; + while let Some((i, j)) = q.pop_front() { + for k in 0..4 { + let x = i as isize + dirs[k]; + let y = j as isize + dirs[k + 1]; + if x >= 0 && x < m as isize && y >= 0 && y < n as isize { + let x = x as usize; + let y = y as usize; + if ans[x][y] == -1 { + ans[x][y] = ans[i][j] + 1; + q.push_back((x, y)); + } } } } - ret_vec - } - - #[allow(dead_code)] - pub fn check_bounds(i: i32, j: i32, n: i32, m: i32) -> bool { - i >= 0 && i < n && j >= 0 && j < m + ans } } ``` diff --git a/solution/0500-0599/0542.01 Matrix/README_EN.md b/solution/0500-0599/0542.01 Matrix/README_EN.md index a81f66566262b..cde08787d2bd3 100644 --- a/solution/0500-0599/0542.01 Matrix/README_EN.md +++ b/solution/0500-0599/0542.01 Matrix/README_EN.md @@ -56,7 +56,17 @@ tags: -### Solution 1 +### Solution 1: BFS + +We create a matrix $\textit{ans}$ of the same size as $\textit{mat}$ and initialize all elements to $-1$. + +Then, we traverse $\textit{mat}$, adding the coordinates $(i, j)$ of all $0$ elements to the queue $\textit{q}$, and setting $\textit{ans}[i][j]$ to $0$. + +Next, we use Breadth-First Search (BFS), removing an element $(i, j)$ from the queue and traversing its four directions. If the element in that direction $(x, y)$ satisfies $0 \leq x < m$, $0 \leq y < n$ and $\textit{ans}[x][y] = -1$, then we set $\textit{ans}[x][y]$ to $\textit{ans}[i][j] + 1$ and add $(x, y)$ to the queue $\textit{q}$. + +Finally, we return $\textit{ans}$. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the number of rows and columns in the matrix $\textit{mat}$, respectively. @@ -209,8 +219,7 @@ function updateMatrix(mat: number[][]): number[][] { } } const dirs: number[] = [-1, 0, 1, 0, -1]; - while (q.length) { - const [i, j] = q.shift()!; + for (const [i, j] of q) { for (let k = 0; k < 4; ++k) { const [x, y] = [i + dirs[k], j + dirs[k + 1]]; if (x >= 0 && x < m && y >= 0 && y < n && ans[x][y] === -1) { @@ -229,49 +238,38 @@ function updateMatrix(mat: number[][]): number[][] { use std::collections::VecDeque; impl Solution { - #[allow(dead_code)] pub fn update_matrix(mat: Vec>) -> Vec> { - let n: usize = mat.len(); - let m: usize = mat[0].len(); - let mut ret_vec: Vec> = vec![vec![-1; m]; n]; - // The inner tuple is of - let mut the_q: VecDeque<(usize, usize)> = VecDeque::new(); - let traverse_vec: Vec<(i32, i32)> = vec![(-1, 0), (1, 0), (0, 1), (0, -1)]; - - // Initialize the queue - for i in 0..n { - for j in 0..m { + let m = mat.len(); + let n = mat[0].len(); + let mut ans = vec![vec![-1; n]; m]; + let mut q = VecDeque::new(); + + for i in 0..m { + for j in 0..n { if mat[i][j] == 0 { - // For the zero cell, enqueue at first - the_q.push_back((i, j)); - // Set to 0 in return vector - ret_vec[i][j] = 0; + q.push_back((i, j)); + ans[i][j] = 0; } } } - while !the_q.is_empty() { - let (x, y) = the_q.front().unwrap().clone(); - the_q.pop_front(); - for pair in &traverse_vec { - let cur_x = pair.0 + (x as i32); - let cur_y = pair.1 + (y as i32); - if Solution::check_bounds(cur_x, cur_y, n as i32, m as i32) - && ret_vec[cur_x as usize][cur_y as usize] == -1 - { - // The current cell has not be updated yet, and is also in bound - ret_vec[cur_x as usize][cur_y as usize] = ret_vec[x][y] + 1; - the_q.push_back((cur_x as usize, cur_y as usize)); + let dirs = [-1, 0, 1, 0, -1]; + while let Some((i, j)) = q.pop_front() { + for k in 0..4 { + let x = i as isize + dirs[k]; + let y = j as isize + dirs[k + 1]; + if x >= 0 && x < m as isize && y >= 0 && y < n as isize { + let x = x as usize; + let y = y as usize; + if ans[x][y] == -1 { + ans[x][y] = ans[i][j] + 1; + q.push_back((x, y)); + } } } } - ret_vec - } - - #[allow(dead_code)] - pub fn check_bounds(i: i32, j: i32, n: i32, m: i32) -> bool { - i >= 0 && i < n && j >= 0 && j < m + ans } } ``` diff --git a/solution/0500-0599/0542.01 Matrix/Solution.rs b/solution/0500-0599/0542.01 Matrix/Solution.rs index 4f6b1f7f38793..4913bce5d043c 100644 --- a/solution/0500-0599/0542.01 Matrix/Solution.rs +++ b/solution/0500-0599/0542.01 Matrix/Solution.rs @@ -1,48 +1,37 @@ use std::collections::VecDeque; impl Solution { - #[allow(dead_code)] pub fn update_matrix(mat: Vec>) -> Vec> { - let n: usize = mat.len(); - let m: usize = mat[0].len(); - let mut ret_vec: Vec> = vec![vec![-1; m]; n]; - // The inner tuple is of - let mut the_q: VecDeque<(usize, usize)> = VecDeque::new(); - let traverse_vec: Vec<(i32, i32)> = vec![(-1, 0), (1, 0), (0, 1), (0, -1)]; + let m = mat.len(); + let n = mat[0].len(); + let mut ans = vec![vec![-1; n]; m]; + let mut q = VecDeque::new(); - // Initialize the queue - for i in 0..n { - for j in 0..m { + for i in 0..m { + for j in 0..n { if mat[i][j] == 0 { - // For the zero cell, enqueue at first - the_q.push_back((i, j)); - // Set to 0 in return vector - ret_vec[i][j] = 0; + q.push_back((i, j)); + ans[i][j] = 0; } } } - while !the_q.is_empty() { - let (x, y) = the_q.front().unwrap().clone(); - the_q.pop_front(); - for pair in &traverse_vec { - let cur_x = pair.0 + (x as i32); - let cur_y = pair.1 + (y as i32); - if Solution::check_bounds(cur_x, cur_y, n as i32, m as i32) - && ret_vec[cur_x as usize][cur_y as usize] == -1 - { - // The current cell has not be updated yet, and is also in bound - ret_vec[cur_x as usize][cur_y as usize] = ret_vec[x][y] + 1; - the_q.push_back((cur_x as usize, cur_y as usize)); + let dirs = [-1, 0, 1, 0, -1]; + while let Some((i, j)) = q.pop_front() { + for k in 0..4 { + let x = i as isize + dirs[k]; + let y = j as isize + dirs[k + 1]; + if x >= 0 && x < m as isize && y >= 0 && y < n as isize { + let x = x as usize; + let y = y as usize; + if ans[x][y] == -1 { + ans[x][y] = ans[i][j] + 1; + q.push_back((x, y)); + } } } } - ret_vec - } - - #[allow(dead_code)] - pub fn check_bounds(i: i32, j: i32, n: i32, m: i32) -> bool { - i >= 0 && i < n && j >= 0 && j < m + ans } } diff --git a/solution/0500-0599/0542.01 Matrix/Solution.ts b/solution/0500-0599/0542.01 Matrix/Solution.ts index d3ec5bf281949..d44cdb2d7e709 100644 --- a/solution/0500-0599/0542.01 Matrix/Solution.ts +++ b/solution/0500-0599/0542.01 Matrix/Solution.ts @@ -11,8 +11,7 @@ function updateMatrix(mat: number[][]): number[][] { } } const dirs: number[] = [-1, 0, 1, 0, -1]; - while (q.length) { - const [i, j] = q.shift()!; + for (const [i, j] of q) { for (let k = 0; k < 4; ++k) { const [x, y] = [i + dirs[k], j + dirs[k + 1]]; if (x >= 0 && x < m && y >= 0 && y < n && ans[x][y] === -1) {