Skip to content

Commit 8b0b46f

Browse files
yanglbmecursoragent
andcommitted
feat: add solutions to lc problem: No.3983
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 04e85d8 commit 8b0b46f

7 files changed

Lines changed: 358 additions & 2 deletions

File tree

solution/3900-3999/3983.Subsequence After One Replacement/README.md

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,32 +70,157 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3900-3999/3983.Su
7070

7171
<!-- solution:start -->
7272

73-
### 方法一
73+
### 方法一:双指针
74+
75+
题目等价于:在将 $s$ 作为 $t$ 的子序列进行贪心匹配时,是否最多允许 $s$ 中有一个字符不匹配(因为该字符可以被替换成任意字母)。
76+
77+
我们用两个指针 $i_0$、$i_1$ 扫描 $s$,同时用指针 $j$ 扫描 $t$:
78+
79+
- $i_0$ 表示在不使用替换的前提下,当前已经匹配到的 $s$ 中的位置;
80+
- $i_1$ 表示在最多使用一次替换的前提下,当前已经匹配到的 $s$ 中的位置。
81+
82+
对于 $t$ 中的每个字符 $t[j]$:
83+
84+
1. 若 $s[i_1] = t[j]$,则将 $i_1$ 右移一位;
85+
2. 令 $i_1 = \max(i_1, i_0 + 1)$,保证替换位置始终不早于 $i_0$,也就是为那一次替换预留一个字符位置;
86+
3. 若 $s[i_0] = t[j]$,则将 $i_0$ 右移一位;
87+
4. 将 $j$ 右移一位。
88+
89+
遍历结束后,若 $i_1 = |s|$,说明在最多替换一个字符的情况下,$s$ 的全部字符都能按顺序匹配到 $t$ 中,返回 `true`;否则返回 `false`
90+
91+
时间复杂度 $O(|s| + |t|)$,空间复杂度 $O(1)$。
7492

7593
<!-- tabs:start -->
7694

7795
#### Python3
7896

7997
```python
98+
class Solution:
99+
def canMakeSubsequence(self, s: str, t: str) -> bool:
100+
m, n = len(s), len(t)
101+
i0 = i1 = j = 0
102+
103+
while i1 < m and j < n:
104+
if s[i1] == t[j]:
105+
i1 += 1
106+
i1 = max(i1, i0 + 1)
80107

108+
if s[i0] == t[j]:
109+
i0 += 1
110+
111+
j += 1
112+
113+
return i1 == m
81114
```
82115

83116
#### Java
84117

85118
```java
119+
class Solution {
120+
public boolean canMakeSubsequence(String s, String t) {
121+
int m = s.length(), n = t.length();
122+
int i0 = 0, i1 = 0, j = 0;
123+
124+
while (i1 < m && j < n) {
125+
if (s.charAt(i1) == t.charAt(j)) {
126+
i1++;
127+
}
128+
129+
i1 = Math.max(i1, i0 + 1);
86130

131+
if (s.charAt(i0) == t.charAt(j)) {
132+
i0++;
133+
}
134+
135+
j++;
136+
}
137+
138+
return i1 == m;
139+
}
140+
}
87141
```
88142

89143
#### C++
90144

91145
```cpp
146+
class Solution {
147+
public:
148+
bool canMakeSubsequence(string s, string t) {
149+
int m = s.size(), n = t.size();
150+
int i0 = 0, i1 = 0, j = 0;
151+
152+
while (i1 < m && j < n) {
153+
if (s[i1] == t[j]) {
154+
i1++;
155+
}
92156

157+
i1 = max(i1, i0 + 1);
158+
159+
if (s[i0] == t[j]) {
160+
i0++;
161+
}
162+
163+
j++;
164+
}
165+
166+
return i1 == m;
167+
}
168+
};
93169
```
94170

95171
#### Go
96172

97173
```go
174+
func canMakeSubsequence(s string, t string) bool {
175+
m, n := len(s), len(t)
176+
i0, i1, j := 0, 0, 0
177+
178+
for i1 < m && j < n {
179+
if s[i1] == t[j] {
180+
i1++
181+
}
182+
183+
if i1 < i0+1 {
184+
i1 = i0 + 1
185+
}
186+
187+
if s[i0] == t[j] {
188+
i0++
189+
}
190+
191+
j++
192+
}
193+
194+
return i1 == m
195+
}
196+
```
197+
198+
#### TypeScript
199+
200+
```ts
201+
function canMakeSubsequence(s: string, t: string): boolean {
202+
const m = s.length,
203+
n = t.length;
204+
let i0 = 0,
205+
i1 = 0,
206+
j = 0;
207+
208+
while (i1 < m && j < n) {
209+
if (s[i1] === t[j]) {
210+
i1++;
211+
}
212+
213+
i1 = Math.max(i1, i0 + 1);
214+
215+
if (s[i0] === t[j]) {
216+
i0++;
217+
}
218+
219+
j++;
220+
}
98221

222+
return i1 === m;
223+
}
99224
```
100225

101226
<!-- tabs:end -->

solution/3900-3999/3983.Subsequence After One Replacement/README_EN.md

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,32 +65,157 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3900-3999/3983.Su
6565

6666
<!-- solution:start -->
6767

68-
### Solution 1
68+
### Solution 1: Two Pointers
69+
70+
The problem is equivalent to asking whether we can greedily match $s$ as a subsequence of $t$ while allowing at most one character in $s$ to mismatch, since that character can be replaced with any letter.
71+
72+
We scan $s$ with two pointers $i_0$ and $i_1$, and scan $t$ with pointer $j$:
73+
74+
- $i_0$ is the current position in $s$ when matching without using the replacement.
75+
- $i_1$ is the current position in $s$ when matching with at most one replacement available.
76+
77+
For each character $t[j]$:
78+
79+
1. If $s[i_1] = t[j]$, move $i_1$ forward by one.
80+
2. Set $i_1 = \max(i_1, i_0 + 1)$ so the replacement position is never before $i_0$, reserving one character for the replacement.
81+
3. If $s[i_0] = t[j]$, move $i_0$ forward by one.
82+
4. Move $j$ forward by one.
83+
84+
After the scan, if $i_1 = |s|$, then all characters of $s$ can be matched in order within $t$ using at most one replacement, so return `true`; otherwise return `false`.
85+
86+
The time complexity is $O(|s| + |t|)$, and the space complexity is $O(1)$.
6987

7088
<!-- tabs:start -->
7189

7290
#### Python3
7391

7492
```python
93+
class Solution:
94+
def canMakeSubsequence(self, s: str, t: str) -> bool:
95+
m, n = len(s), len(t)
96+
i0 = i1 = j = 0
97+
98+
while i1 < m and j < n:
99+
if s[i1] == t[j]:
100+
i1 += 1
101+
i1 = max(i1, i0 + 1)
75102

103+
if s[i0] == t[j]:
104+
i0 += 1
105+
106+
j += 1
107+
108+
return i1 == m
76109
```
77110

78111
#### Java
79112

80113
```java
114+
class Solution {
115+
public boolean canMakeSubsequence(String s, String t) {
116+
int m = s.length(), n = t.length();
117+
int i0 = 0, i1 = 0, j = 0;
118+
119+
while (i1 < m && j < n) {
120+
if (s.charAt(i1) == t.charAt(j)) {
121+
i1++;
122+
}
123+
124+
i1 = Math.max(i1, i0 + 1);
81125

126+
if (s.charAt(i0) == t.charAt(j)) {
127+
i0++;
128+
}
129+
130+
j++;
131+
}
132+
133+
return i1 == m;
134+
}
135+
}
82136
```
83137

84138
#### C++
85139

86140
```cpp
141+
class Solution {
142+
public:
143+
bool canMakeSubsequence(string s, string t) {
144+
int m = s.size(), n = t.size();
145+
int i0 = 0, i1 = 0, j = 0;
146+
147+
while (i1 < m && j < n) {
148+
if (s[i1] == t[j]) {
149+
i1++;
150+
}
87151

152+
i1 = max(i1, i0 + 1);
153+
154+
if (s[i0] == t[j]) {
155+
i0++;
156+
}
157+
158+
j++;
159+
}
160+
161+
return i1 == m;
162+
}
163+
};
88164
```
89165

90166
#### Go
91167

92168
```go
169+
func canMakeSubsequence(s string, t string) bool {
170+
m, n := len(s), len(t)
171+
i0, i1, j := 0, 0, 0
172+
173+
for i1 < m && j < n {
174+
if s[i1] == t[j] {
175+
i1++
176+
}
177+
178+
if i1 < i0+1 {
179+
i1 = i0 + 1
180+
}
181+
182+
if s[i0] == t[j] {
183+
i0++
184+
}
185+
186+
j++
187+
}
188+
189+
return i1 == m
190+
}
191+
```
192+
193+
#### TypeScript
194+
195+
```ts
196+
function canMakeSubsequence(s: string, t: string): boolean {
197+
const m = s.length,
198+
n = t.length;
199+
let i0 = 0,
200+
i1 = 0,
201+
j = 0;
202+
203+
while (i1 < m && j < n) {
204+
if (s[i1] === t[j]) {
205+
i1++;
206+
}
207+
208+
i1 = Math.max(i1, i0 + 1);
209+
210+
if (s[i0] === t[j]) {
211+
i0++;
212+
}
213+
214+
j++;
215+
}
93216

217+
return i1 === m;
218+
}
94219
```
95220

96221
<!-- tabs:end -->
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Solution {
2+
public:
3+
bool canMakeSubsequence(string s, string t) {
4+
int m = s.size(), n = t.size();
5+
int i0 = 0, i1 = 0, j = 0;
6+
7+
while (i1 < m && j < n) {
8+
if (s[i1] == t[j]) {
9+
i1++;
10+
}
11+
12+
i1 = max(i1, i0 + 1);
13+
14+
if (s[i0] == t[j]) {
15+
i0++;
16+
}
17+
18+
j++;
19+
}
20+
21+
return i1 == m;
22+
}
23+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
func canMakeSubsequence(s string, t string) bool {
2+
m, n := len(s), len(t)
3+
i0, i1, j := 0, 0, 0
4+
5+
for i1 < m && j < n {
6+
if s[i1] == t[j] {
7+
i1++
8+
}
9+
10+
if i1 < i0+1 {
11+
i1 = i0 + 1
12+
}
13+
14+
if s[i0] == t[j] {
15+
i0++
16+
}
17+
18+
j++
19+
}
20+
21+
return i1 == m
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class Solution {
2+
public boolean canMakeSubsequence(String s, String t) {
3+
int m = s.length(), n = t.length();
4+
int i0 = 0, i1 = 0, j = 0;
5+
6+
while (i1 < m && j < n) {
7+
if (s.charAt(i1) == t.charAt(j)) {
8+
i1++;
9+
}
10+
11+
i1 = Math.max(i1, i0 + 1);
12+
13+
if (s.charAt(i0) == t.charAt(j)) {
14+
i0++;
15+
}
16+
17+
j++;
18+
}
19+
20+
return i1 == m;
21+
}
22+
}

0 commit comments

Comments
 (0)