Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e51cd08

Browse files
feat: add rust solution to lc problem: No.3579 (doocs#4482)
No.3579.Minimum Steps to Convert String with Operations
1 parent 22c6a2b commit e51cd08

File tree

3 files changed

+158
-2
lines changed

3 files changed

+158
-2
lines changed

‎solution/3500-3599/3579.Minimum Steps to Convert String with Operations/README.md‎

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,17 @@ tags:
144144

145145
<!-- solution:start -->
146146

147-
### 方法一
147+
### 方法一:贪心 + 动态规划
148+
149+
我们定义 $f[i]$ 表示将 $\textit{word1}$ 的前 $i$ 个字符转换为 $\textit{word2}$ 的前 $i$ 个字符所需的最小操作数。那么答案为 $f[n],ドル其中 $n$ 是 $\textit{word1}$ 和 $\textit{word2}$ 的长度。
150+
151+
我们可以通过遍历所有可能的分割点来计算 $f[i]$。对于每个分割点 $j,ドル我们需要计算将 $\textit{word1}[j:i]$ 转换为 $\textit{word2}[j:i]$ 所需的最小操作数。
152+
153+
我们可以使用一个辅助函数 $\text{calc}(l, r, \text{rev})$ 来计算从 $\textit{word1}[l:r]$ 转换为 $\textit{word2}[l:r]$ 所需的最小操作数,其中 $\text{rev}$ 表示是否需要反转子串。由于反转前后进行其它操作的结果是一样的,所以我们可以考虑不反转,以及首先进行一次反转后再进行其它操作。因此有 $f[i] = \min_{j < i} (f[j] + \min(\text{calc}(j, i-1, \text{false}), 1 + \text{calc}(j, i-1, \text{true})))$。
154+
155+
接下来我们需要实现 $\text{calc}(l, r, \text{rev})$ 函数。我们用一个二维数组 $cnt$ 来记录 $\textit{word1}$ 和 $\textit{word2}$ 中字符的配对情况。对于每个字符对 $(a, b),ドル如果 $a \neq b,ドル我们需要检查 $cnt[b][a]$ 是否大于 0ドル$。如果是,我们可以将其配对,减少一次操作;否则,我们需要增加一次操作,并将 $cnt[a][b]$ 加 1ドル$。
156+
157+
时间复杂度 $O(n^3 + |\Sigma|^2),ドル空间复杂度 $O(n + |\Sigma|^2),ドル其中 $n$ 是字符串的长度,而 $|\Sigma|$ 是字符集大小(本题中为 26ドル$)。
148158

149159
<!-- tabs:start -->
150160

@@ -357,6 +367,53 @@ function minOperations(word1: string, word2: string): number {
357367
}
358368
```
359369

370+
#### Rust
371+
372+
```rust
373+
impl Solution {
374+
pub fn min_operations(word1: String, word2: String) -> i32 {
375+
let n = word1.len();
376+
let word1 = word1.as_bytes();
377+
let word2 = word2.as_bytes();
378+
let mut f = vec![i32::MAX; n + 1];
379+
f[0] = 0;
380+
381+
for i in 1..=n {
382+
for j in 0..i {
383+
let a = Self::calc(word1, word2, j, i - 1, false);
384+
let b = 1 + Self::calc(word1, word2, j, i - 1, true);
385+
let t = a.min(b);
386+
f[i] = f[i].min(f[j] + t);
387+
}
388+
}
389+
390+
f[n]
391+
}
392+
393+
fn calc(word1: &[u8], word2: &[u8], l: usize, r: usize, rev: bool) -> i32 {
394+
let mut cnt = [[0i32; 26]; 26];
395+
let mut res = 0;
396+
397+
for i in l..=r {
398+
let j = if rev { r - (i - l) } else { i };
399+
let a = (word1[j] - b'a') as usize;
400+
let b = (word2[i] - b'a') as usize;
401+
402+
if a != b {
403+
if cnt[b][a] > 0 {
404+
cnt[b][a] -= 1;
405+
} else {
406+
cnt[a][b] += 1;
407+
res += 1;
408+
}
409+
}
410+
}
411+
412+
res
413+
}
414+
}
415+
```
416+
360417
<!-- tabs:end -->
361418

362419
<!-- solution:end -->

‎solution/3500-3599/3579.Minimum Steps to Convert String with Operations/README_EN.md‎

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,17 @@ tags:
139139

140140
<!-- solution:start -->
141141

142-
### Solution 1
142+
### Solution 1: Greedy + Dynamic Programming
143+
144+
We define $f[i]$ as the minimum number of operations required to convert the first $i$ characters of $\textit{word1}$ to the first $i$ characters of $\textit{word2}$. The answer is $f[n],ドル where $n$ is the length of both $\textit{word1}$ and $\textit{word2}$.
145+
146+
We can compute $f[i]$ by enumerating all possible split points. For each split point $j,ドル we need to calculate the minimum number of operations required to convert $\textit{word1}[j:i]$ to $\textit{word2}[j:i]$.
147+
148+
We can use a helper function $\text{calc}(l, r, \text{rev})$ to compute the minimum number of operations needed to convert $\textit{word1}[l:r]$ to $\textit{word2}[l:r],ドル where $\text{rev}$ indicates whether to reverse the substring. Since the result of performing other operations before or after a reversal is the same, we only need to consider not reversing, and reversing once before other operations. Therefore, $f[i] = \min_{j < i} (f[j] + \min(\text{calc}(j, i-1, \text{false}), 1 + \text{calc}(j, i-1, \text{true})))$.
149+
150+
Next, we need to implement the $\text{calc}(l, r, \text{rev})$ function. We use a 2D array $cnt$ to record the pairing status of characters between $\textit{word1}$ and $\textit{word2}$. For each character pair $(a, b),ドル if $a \neq b,ドル we check whether $cnt[b][a] > 0$. If so, we can pair them and reduce one operation; otherwise, we need to add one operation and increment $cnt[a][b]$ by 1ドル$.
151+
152+
The time complexity is $O(n^3 + |\Sigma|^2)$ and the space complexity is $O(n + |\Sigma|^2),ドル where $n$ is the length of the string and $|\Sigma|$ is the size of the character set (which is 26ドル$ in this problem).
143153

144154
<!-- tabs:start -->
145155

@@ -352,6 +362,53 @@ function minOperations(word1: string, word2: string): number {
352362
}
353363
```
354364

365+
#### Rust
366+
367+
```rust
368+
impl Solution {
369+
pub fn min_operations(word1: String, word2: String) -> i32 {
370+
let n = word1.len();
371+
let word1 = word1.as_bytes();
372+
let word2 = word2.as_bytes();
373+
let mut f = vec![i32::MAX; n + 1];
374+
f[0] = 0;
375+
376+
for i in 1..=n {
377+
for j in 0..i {
378+
let a = Self::calc(word1, word2, j, i - 1, false);
379+
let b = 1 + Self::calc(word1, word2, j, i - 1, true);
380+
let t = a.min(b);
381+
f[i] = f[i].min(f[j] + t);
382+
}
383+
}
384+
385+
f[n]
386+
}
387+
388+
fn calc(word1: &[u8], word2: &[u8], l: usize, r: usize, rev: bool) -> i32 {
389+
let mut cnt = [[0i32; 26]; 26];
390+
let mut res = 0;
391+
392+
for i in l..=r {
393+
let j = if rev { r - (i - l) } else { i };
394+
let a = (word1[j] - b'a') as usize;
395+
let b = (word2[i] - b'a') as usize;
396+
397+
if a != b {
398+
if cnt[b][a] > 0 {
399+
cnt[b][a] -= 1;
400+
} else {
401+
cnt[a][b] += 1;
402+
res += 1;
403+
}
404+
}
405+
}
406+
407+
res
408+
}
409+
}
410+
```
411+
355412
<!-- tabs:end -->
356413

357414
<!-- solution:end -->
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
impl Solution {
2+
pub fn min_operations(word1: String, word2: String) -> i32 {
3+
let n = word1.len();
4+
let word1 = word1.as_bytes();
5+
let word2 = word2.as_bytes();
6+
let mut f = vec![i32::MAX; n + 1];
7+
f[0] = 0;
8+
9+
for i in 1..=n {
10+
for j in 0..i {
11+
let a = Self::calc(word1, word2, j, i - 1, false);
12+
let b = 1 + Self::calc(word1, word2, j, i - 1, true);
13+
let t = a.min(b);
14+
f[i] = f[i].min(f[j] + t);
15+
}
16+
}
17+
18+
f[n]
19+
}
20+
21+
fn calc(word1: &[u8], word2: &[u8], l: usize, r: usize, rev: bool) -> i32 {
22+
let mut cnt = [[0i32; 26]; 26];
23+
let mut res = 0;
24+
25+
for i in l..=r {
26+
let j = if rev { r - (i - l) } else { i };
27+
let a = (word1[j] - b'a') as usize;
28+
let b = (word2[i] - b'a') as usize;
29+
30+
if a != b {
31+
if cnt[b][a] > 0 {
32+
cnt[b][a] -= 1;
33+
} else {
34+
cnt[a][b] += 1;
35+
res += 1;
36+
}
37+
}
38+
}
39+
40+
res
41+
}
42+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /