Skip to content

Commit 3d0f346

Browse files
committed
feat: add Rust solution for lc No.3714
1 parent f6dc815 commit 3d0f346

File tree

3 files changed

+330
-2
lines changed

3 files changed

+330
-2
lines changed

solution/3700-3799/3714.Longest Balanced Substring II/README.md

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,25 @@ tags:
8282

8383
<!-- solution:start -->
8484

85-
### 方法一
85+
### 方法一:枚举 + 前缀和 + 哈希表
86+
87+
答案分为以下三种情况:
88+
89+
1. 平衡子串中只有一种字符,例如 `"aaa"`
90+
2. 平衡子串中有两种字符,例如 `"aabb"`
91+
3. 平衡子串中有三种字符,例如 `"abc"`
92+
93+
我们分别定义三个函数 $\text{calc1}(s)$、$\text{calc2}(s, a, b)$ 和 $\text{calc3}(s)$ 来计算上述三种情况的最长平衡子串长度,最后返回三者的最大值。
94+
95+
对于 $\text{calc1}(s)$,我们只需要遍历字符串 $s$,统计每个连续字符的长度,取最大值即可。
96+
97+
对于 $\text{calc2}(s, a, b)$,我们可以使用前缀和和哈希表来计算最长的平衡子串长度。具体来说,我们维护一个变量 $d$ 来表示当前子串中字符 $a$ 的数量减去字符 $b$ 的数量,并使用一个哈希表来记录每个 $d$ 值第一次出现的位置。当我们再次遇到相同的 $d$ 值时,说明从上一次出现的位置到当前位置的子串中字符 $a$ 和字符 $b$ 的数量相等,即该子串是平衡的,我们更新答案。
98+
99+
对于 $\text{calc3}(s)$,我们同样使用前缀和和哈希表来计算最长的平衡子串长度。我们定义一个数组 $\textit{cnt}$ 来记录字符 $a$, $b$ 和 $c$ 的数量,并使用一个哈希表来记录每个 $(\textit{cnt}[a] - \textit{cnt}[b], \textit{cnt}[b] - \textit{cnt}[c])$ 值第一次出现的位置。当我们再次遇到相同的值时,说明从上一次出现的位置到当前位置的子串中字符 $a$, $b$ 和 $c$ 的数量相等,即该子串是平衡的,我们更新答案。
100+
101+
最后,我们分别计算 $\text{calc1}(s)$、$\text{calc2}(s, 'a', 'b')$、$\text{calc2}(s, 'b', 'c')$、$\text{calc2}(s, 'a', 'c')$ 和 $\text{calc3}(s)$ 的值,返回它们的最大值即可。
102+
103+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。
86104

87105
<!-- tabs:start -->
88106

@@ -467,6 +485,105 @@ function key(x: number, y: number): string {
467485
}
468486
```
469487

488+
#### Rust
489+
490+
```rust
491+
use std::collections::HashMap;
492+
493+
impl Solution {
494+
pub fn longest_balanced(s: String) -> i32 {
495+
let x = Self::calc1(&s);
496+
let y = Self::calc2(&s, 'a', 'b')
497+
.max(Self::calc2(&s, 'b', 'c'))
498+
.max(Self::calc2(&s, 'a', 'c'));
499+
let z = Self::calc3(&s);
500+
x.max(y).max(z)
501+
}
502+
503+
fn calc1(s: &str) -> i32 {
504+
let bytes = s.as_bytes();
505+
let mut res = 0i32;
506+
let mut i = 0usize;
507+
let n = bytes.len();
508+
509+
while i < n {
510+
let mut j = i + 1;
511+
while j < n && bytes[j] == bytes[i] {
512+
j += 1;
513+
}
514+
res = res.max((j - i) as i32);
515+
i = j;
516+
}
517+
res
518+
}
519+
520+
fn calc2(s: &str, a: char, b: char) -> i32 {
521+
let bytes = s.as_bytes();
522+
let a = a as u8;
523+
let b = b as u8;
524+
525+
let mut res = 0i32;
526+
let mut i = 0usize;
527+
let n = bytes.len();
528+
529+
while i < n {
530+
while i < n && bytes[i] != a && bytes[i] != b {
531+
i += 1;
532+
}
533+
534+
let mut pos: HashMap<i32, i32> = HashMap::new();
535+
pos.insert(0, i as i32 - 1);
536+
537+
let mut d = 0i32;
538+
while i < n && (bytes[i] == a || bytes[i] == b) {
539+
if bytes[i] == a {
540+
d += 1;
541+
} else {
542+
d -= 1;
543+
}
544+
545+
if let Some(&pre) = pos.get(&d) {
546+
res = res.max(i as i32 - pre);
547+
} else {
548+
pos.insert(d, i as i32);
549+
}
550+
i += 1;
551+
}
552+
}
553+
554+
res
555+
}
556+
557+
fn f(x: i32, y: i32) -> i64 {
558+
(((x + 100000) as i64) << 20) | ((y + 100000) as i64)
559+
}
560+
561+
fn calc3(s: &str) -> i32 {
562+
let mut pos: HashMap<i64, i32> = HashMap::new();
563+
pos.insert(Self::f(0, 0), -1);
564+
565+
let mut cnt = [0i32; 3];
566+
let mut res = 0i32;
567+
568+
for (i, c) in s.bytes().enumerate() {
569+
cnt[(c - b'a') as usize] += 1;
570+
571+
let x = cnt[0] - cnt[1];
572+
let y = cnt[1] - cnt[2];
573+
let k = Self::f(x, y);
574+
575+
if let Some(&pre) = pos.get(&k) {
576+
res = res.max(i as i32 - pre);
577+
} else {
578+
pos.insert(k, i as i32);
579+
}
580+
}
581+
582+
res
583+
}
584+
}
585+
```
586+
470587
<!-- tabs:end -->
471588

472589
<!-- solution:end -->

solution/3700-3799/3714.Longest Balanced Substring II/README_EN.md

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,25 @@ tags:
7777

7878
<!-- solution:start -->
7979

80-
### Solution 1
80+
### Solution 1: Enumeration + Prefix Sum + Hash Table
81+
82+
The answer is divided into the following three cases:
83+
84+
1. Balanced substring with only one character, such as `"aaa"`.
85+
2. Balanced substring with two characters, such as `"aabb"`.
86+
3. Balanced substring with three characters, such as `"abc"`.
87+
88+
We define three functions $\text{calc1}(s)$, $\text{calc2}(s, a, b)$, and $\text{calc3}(s)$ to calculate the longest balanced substring length for the above three cases respectively, and finally return the maximum of the three.
89+
90+
For $\text{calc1}(s)$, we only need to traverse the string $s$, count the length of each consecutive character, and take the maximum value.
91+
92+
For $\text{calc2}(s, a, b)$, we can use prefix sum and hash table to calculate the longest balanced substring length. Specifically, we maintain a variable $d$ to represent the number of character $a$ minus the number of character $b$ in the current substring, and use a hash table to record the first occurrence position of each $d$ value. When we encounter the same $d$ value again, it means that the number of character $a$ and character $b$ in the substring from the last occurrence position to the current position are equal, i.e., the substring is balanced, and we update the answer.
93+
94+
For $\text{calc3}(s)$, we also use prefix sum and hash table to calculate the longest balanced substring length. We define an array $\textit{cnt}$ to record the counts of characters $a$, $b$, and $c$, and use a hash table to record the first occurrence position of each $(\textit{cnt}[a] - \textit{cnt}[b], \textit{cnt}[b] - \textit{cnt}[c])$ value. When we encounter the same value again, it means that the counts of characters $a$, $b$, and $c$ in the substring from the last occurrence position to the current position are equal, i.e., the substring is balanced, and we update the answer.
95+
96+
Finally, we calculate the values of $\text{calc1}(s)$, $\text{calc2}(s, 'a', 'b')$, $\text{calc2}(s, 'b', 'c')$, $\text{calc2}(s, 'a', 'c')$, and $\text{calc3}(s)$ respectively, and return their maximum value.
97+
98+
The time complexity is $O(n)$ and the space complexity is $O(n)$, where $n$ is the length of the string $s$.
8199

82100
<!-- tabs:start -->
83101

@@ -462,6 +480,105 @@ function key(x: number, y: number): string {
462480
}
463481
```
464482

483+
#### Rust
484+
485+
```rust
486+
use std::collections::HashMap;
487+
488+
impl Solution {
489+
pub fn longest_balanced(s: String) -> i32 {
490+
let x = Self::calc1(&s);
491+
let y = Self::calc2(&s, 'a', 'b')
492+
.max(Self::calc2(&s, 'b', 'c'))
493+
.max(Self::calc2(&s, 'a', 'c'));
494+
let z = Self::calc3(&s);
495+
x.max(y).max(z)
496+
}
497+
498+
fn calc1(s: &str) -> i32 {
499+
let bytes = s.as_bytes();
500+
let mut res = 0i32;
501+
let mut i = 0usize;
502+
let n = bytes.len();
503+
504+
while i < n {
505+
let mut j = i + 1;
506+
while j < n && bytes[j] == bytes[i] {
507+
j += 1;
508+
}
509+
res = res.max((j - i) as i32);
510+
i = j;
511+
}
512+
res
513+
}
514+
515+
fn calc2(s: &str, a: char, b: char) -> i32 {
516+
let bytes = s.as_bytes();
517+
let a = a as u8;
518+
let b = b as u8;
519+
520+
let mut res = 0i32;
521+
let mut i = 0usize;
522+
let n = bytes.len();
523+
524+
while i < n {
525+
while i < n && bytes[i] != a && bytes[i] != b {
526+
i += 1;
527+
}
528+
529+
let mut pos: HashMap<i32, i32> = HashMap::new();
530+
pos.insert(0, i as i32 - 1);
531+
532+
let mut d = 0i32;
533+
while i < n && (bytes[i] == a || bytes[i] == b) {
534+
if bytes[i] == a {
535+
d += 1;
536+
} else {
537+
d -= 1;
538+
}
539+
540+
if let Some(&pre) = pos.get(&d) {
541+
res = res.max(i as i32 - pre);
542+
} else {
543+
pos.insert(d, i as i32);
544+
}
545+
i += 1;
546+
}
547+
}
548+
549+
res
550+
}
551+
552+
fn f(x: i32, y: i32) -> i64 {
553+
(((x + 100000) as i64) << 20) | ((y + 100000) as i64)
554+
}
555+
556+
fn calc3(s: &str) -> i32 {
557+
let mut pos: HashMap<i64, i32> = HashMap::new();
558+
pos.insert(Self::f(0, 0), -1);
559+
560+
let mut cnt = [0i32; 3];
561+
let mut res = 0i32;
562+
563+
for (i, c) in s.bytes().enumerate() {
564+
cnt[(c - b'a') as usize] += 1;
565+
566+
let x = cnt[0] - cnt[1];
567+
let y = cnt[1] - cnt[2];
568+
let k = Self::f(x, y);
569+
570+
if let Some(&pre) = pos.get(&k) {
571+
res = res.max(i as i32 - pre);
572+
} else {
573+
pos.insert(k, i as i32);
574+
}
575+
}
576+
577+
res
578+
}
579+
}
580+
```
581+
465582
<!-- tabs:end -->
466583

467584
<!-- solution:end -->
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use std::collections::HashMap;
2+
3+
impl Solution {
4+
pub fn longest_balanced(s: String) -> i32 {
5+
let x = Self::calc1(&s);
6+
let y = Self::calc2(&s, 'a', 'b')
7+
.max(Self::calc2(&s, 'b', 'c'))
8+
.max(Self::calc2(&s, 'a', 'c'));
9+
let z = Self::calc3(&s);
10+
x.max(y).max(z)
11+
}
12+
13+
fn calc1(s: &str) -> i32 {
14+
let bytes = s.as_bytes();
15+
let mut res = 0i32;
16+
let mut i = 0usize;
17+
let n = bytes.len();
18+
19+
while i < n {
20+
let mut j = i + 1;
21+
while j < n && bytes[j] == bytes[i] {
22+
j += 1;
23+
}
24+
res = res.max((j - i) as i32);
25+
i = j;
26+
}
27+
res
28+
}
29+
30+
fn calc2(s: &str, a: char, b: char) -> i32 {
31+
let bytes = s.as_bytes();
32+
let a = a as u8;
33+
let b = b as u8;
34+
35+
let mut res = 0i32;
36+
let mut i = 0usize;
37+
let n = bytes.len();
38+
39+
while i < n {
40+
while i < n && bytes[i] != a && bytes[i] != b {
41+
i += 1;
42+
}
43+
44+
let mut pos: HashMap<i32, i32> = HashMap::new();
45+
pos.insert(0, i as i32 - 1);
46+
47+
let mut d = 0i32;
48+
while i < n && (bytes[i] == a || bytes[i] == b) {
49+
if bytes[i] == a {
50+
d += 1;
51+
} else {
52+
d -= 1;
53+
}
54+
55+
if let Some(&pre) = pos.get(&d) {
56+
res = res.max(i as i32 - pre);
57+
} else {
58+
pos.insert(d, i as i32);
59+
}
60+
i += 1;
61+
}
62+
}
63+
64+
res
65+
}
66+
67+
fn f(x: i32, y: i32) -> i64 {
68+
(((x + 100000) as i64) << 20) | ((y + 100000) as i64)
69+
}
70+
71+
fn calc3(s: &str) -> i32 {
72+
let mut pos: HashMap<i64, i32> = HashMap::new();
73+
pos.insert(Self::f(0, 0), -1);
74+
75+
let mut cnt = [0i32; 3];
76+
let mut res = 0i32;
77+
78+
for (i, c) in s.bytes().enumerate() {
79+
cnt[(c - b'a') as usize] += 1;
80+
81+
let x = cnt[0] - cnt[1];
82+
let y = cnt[1] - cnt[2];
83+
let k = Self::f(x, y);
84+
85+
if let Some(&pre) = pos.get(&k) {
86+
res = res.max(i as i32 - pre);
87+
} else {
88+
pos.insert(k, i as i32);
89+
}
90+
}
91+
92+
res
93+
}
94+
}

0 commit comments

Comments
 (0)