55
55
56
56
<!-- 这里可写通用的实现逻辑 -->
57
57
58
- 前缀和 + 二分查找。
58
+ ** 方法一:前缀和 + 二分查找**
59
+
60
+ 我们可以创建一个长度为 $n + 1$ 的数组 $f$,其中 $f[ i] $ 表示字符串 $s$ 的前 $i$ 个字符与字符串 $t$ 的前 $i$ 个字符的 ASCII 码值的差的绝对值之和。这样,我们就可以通过 $f[ j + 1] - f[ i] $ 来计算字符串 $s$ 的第 $i$ 个字符到第 $j$ 个字符的 ASCII 码值的差的绝对值之和,其中 $0 \leq i \leq j < n$。
61
+
62
+ 注意到长度具有单调性,即如果存在长度为 $x$ 的子串满足条件,那么长度为 $x - 1$ 的子串也一定满足条件。因此,我们可以使用二分查找的方法来求解最大长度。
63
+
64
+ 我们定义函数 $check(x)$,表示是否存在长度为 $x$ 的子串满足条件。在该函数中,我们只需要枚举所有长度为 $x$ 的子串,判断其是否满足条件即可。如果存在满足条件的子串,那么函数返回 ` true ` ,否则返回 ` false ` 。
65
+
66
+ 接下来,我们定义二分查找的左边界 $l$ 为 $0$,右边界 $r$ 为 $n$。在每一步中,我们令 $mid = \lfloor \frac{l + r + 1}{2} \rfloor$,如果函数 $check(mid)$ 的返回值为 ` true ` ,那么我们将左边界更新为 $mid$,否则我们将右边界更新为 $mid - 1$。在二分查找结束后,我们得到的左边界即为答案。
67
+
68
+ 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。
69
+
70
+ ** 方法二:双指针**
71
+
72
+ 我们可以维护两个指针 $j$ 和 $i$,初始时 $i = j = 0$;维护一个变量 $sum$,表示下标区间 $[ i,..j] $ 之间的 ASCII 码值的差的绝对值之和。在每一步中,我们将 $i$ 向右移动一位,然后更新 $sum = sum + |s[ i] - t[ i] |$。如果 $sum \gt maxCost$,那么我们就循环将指针 $j$ 向右移动,并且在移动过程中不断减少 $sum$ 的值,直到 $sum \leq maxCost$。然后我们更新答案,即 $ans = \max(ans, i - j + 1)$。
73
+
74
+ 最后返回答案即可。
75
+
76
+ 时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为字符串 $s$ 的长度。
59
77
60
78
<!-- tabs:start -->
61
79
66
84
``` python
67
85
class Solution :
68
86
def equalSubstring (self , s : str , t : str , maxCost : int ) -> int :
69
- n = len (s)
70
- presum = [0 ] * (n + 1 )
71
- for i in range (n):
72
- presum[i + 1 ] = presum[i] + abs (ord (s[i]) - ord (t[i]))
73
- left, right = 0 , n
74
-
75
- def check (l ):
76
- i = 0
77
- while i + l - 1 < n:
78
- j = i + l - 1
79
- if presum[j + 1 ] - presum[i] <= maxCost:
87
+ def check (x ):
88
+ for i in range (n):
89
+ j = i + mid - 1
90
+ if j < n and f[j + 1 ] - f[i] <= maxCost:
80
91
return True
81
- i += 1
82
92
return False
83
93
84
- while left < right:
85
- mid = (left + right + 1 ) >> 1
94
+ n = len (s)
95
+ f = list (accumulate((abs (ord (a) - ord (b))
96
+ for a, b in zip (s, t)), initial = 0 ))
97
+ l, r = 0 , n
98
+ while l < r:
99
+ mid = (l + r + 1 ) >> 1
86
100
if check(mid):
87
- left = mid
101
+ l = mid
88
102
else :
89
- right = mid - 1
90
- return left
103
+ r = mid - 1
104
+ return l
105
+ ```
106
+
107
+ ``` python
108
+ class Solution :
109
+ def equalSubstring (self , s : str , t : str , maxCost : int ) -> int :
110
+ n = len (s)
111
+ sum = j = 0
112
+ ans = 0
113
+ for i in range (n):
114
+ sum += abs (ord (s[i]) - ord (t[i]))
115
+ while sum > maxCost:
116
+ sum -= abs (ord (s[j]) - ord (t[j]))
117
+ j += 1
118
+ ans = max (ans, i - j + 1 )
119
+ return ans
91
120
```
92
121
93
122
### ** Java**
@@ -96,66 +125,111 @@ class Solution:
96
125
97
126
``` java
98
127
class Solution {
128
+ private int maxCost;
129
+ private int [] f;
130
+ private int n;
131
+
99
132
public int equalSubstring (String s , String t , int maxCost ) {
100
- int n = s. length();
101
- int [] presum = new int [n + 1 ];
133
+ n = s. length();
134
+ f = new int [n + 1 ];
135
+ this . maxCost = maxCost;
102
136
for (int i = 0 ; i < n; ++ i) {
103
- presum[i + 1 ] = presum[i] + Math . abs(s. charAt(i) - t. charAt(i));
137
+ int x = Math . abs(s. charAt(i) - t. charAt(i));
138
+ f[i + 1 ] = f[i] + x;
104
139
}
105
- int left = 0 , right = n;
106
- while (left < right ) {
107
- int mid = (left + right + 1 ) >>> 1 ;
108
- if (check(mid, presum, maxCost, n )) {
109
- left = mid;
140
+ int l = 0 , r = n;
141
+ while (l < r ) {
142
+ int mid = (l + r + 1 ) >>> 1 ;
143
+ if (check(mid)) {
144
+ l = mid;
110
145
} else {
111
- right = mid - 1 ;
146
+ r = mid - 1 ;
112
147
}
113
148
}
114
- return left ;
149
+ return l ;
115
150
}
116
151
117
- private boolean check (int l , int [] s , int maxCost , int n ) {
118
- int i = 0 ;
119
- while (i + l - 1 < n) {
120
- int j = i + l - 1 ;
121
- if (s[j + 1 ] - s[i] <= maxCost) {
152
+ private boolean check (int x ) {
153
+ for (int i = 0 ; i + x - 1 < n; ++ i) {
154
+ int j = i + x - 1 ;
155
+ if (f[j + 1 ] - f[i] <= maxCost) {
122
156
return true ;
123
157
}
124
- ++ i;
125
158
}
126
159
return false ;
127
160
}
128
161
}
129
162
```
130
163
164
+ ``` java
165
+ class Solution {
166
+ public int equalSubstring (String s , String t , int maxCost ) {
167
+ int n = s. length();
168
+ int sum = 0 ;
169
+ int ans = 0 ;
170
+ for (int i = 0 , j = 0 ; i < n; ++ i) {
171
+ sum += Math . abs(s. charAt(i) - t. charAt(i));
172
+ while (sum > maxCost) {
173
+ sum -= Math . abs(s. charAt(j) - t. charAt(j));
174
+ ++ j;
175
+ }
176
+ ans = Math . max(ans, i - j + 1 );
177
+ }
178
+ return ans;
179
+ }
180
+ }
181
+ ```
182
+
131
183
### ** C++**
132
184
133
185
``` cpp
134
186
class Solution {
135
187
public:
136
188
int equalSubstring(string s, string t, int maxCost) {
137
189
int n = s.size();
138
- vector<int > presum(n + 1);
139
- for (int i = 0; i < n; ++i) presum[ i + 1] = presum[ i] + abs(s[ i] - t[ i] );
140
- int left = 0, right = n;
141
- while (left < right) {
142
- int mid = left + right + 1 >> 1;
143
- if (check(mid, presum, maxCost, n))
144
- left = mid;
145
- else
146
- right = mid - 1;
190
+ int f[ n + 1] ;
191
+ f[ 0] = 0;
192
+ for (int i = 0; i < n; ++i) {
193
+ f[ i + 1] = f[ i] + abs(s[ i] - t[ i] );
194
+ }
195
+ auto check = [ &] (int x) -> bool {
196
+ for (int i = 0; i + x - 1 < n; ++i) {
197
+ int j = i + x - 1;
198
+ if (f[ j + 1] - f[ i] <= maxCost) {
199
+ return true;
200
+ }
201
+ }
202
+ return false;
203
+ };
204
+ int l = 0, r = n;
205
+ while (l < r) {
206
+ int mid = (l + r + 1) >> 1;
207
+ if (check(mid)) {
208
+ l = mid;
209
+ } else {
210
+ r = mid - 1;
211
+ }
147
212
}
148
- return left ;
213
+ return l ;
149
214
}
215
+ };
216
+ ```
150
217
151
- bool check(int l, vector<int>& s, int maxCost, int n) {
152
- int i = 0;
153
- while (i + l - 1 < n) {
154
- int j = i + l - 1;
155
- if (s[j + 1] - s[i] <= maxCost) return true;
156
- ++i;
218
+ ```cpp
219
+ class Solution {
220
+ public:
221
+ int equalSubstring(string s, string t, int maxCost) {
222
+ int n = s.size();
223
+ int ans = 0, sum = 0;
224
+ for (int i = 0, j = 0; i < n; ++i) {
225
+ sum += abs(s[i] - t[i]);
226
+ while (sum > maxCost) {
227
+ sum -= abs(s[j] - t[j]);
228
+ ++j;
229
+ }
230
+ ans = max(ans, i - j + 1);
157
231
}
158
- return false ;
232
+ return ans ;
159
233
}
160
234
};
161
235
```
@@ -165,39 +239,58 @@ public:
165
239
``` go
166
240
func equalSubstring (s string , t string , maxCost int ) int {
167
241
n := len (s)
168
- presum := make ([]int , n+1 )
169
- for i , c := range s {
170
- presum [i+1 ] = presum [i] + abs (int (c )-int (t[i]))
242
+ f := make ([]int , n+1 )
243
+ for i , a := range s {
244
+ f [i+1 ] = f [i] + abs (int (a )-int (t[i]))
171
245
}
172
-
173
- left , right := 0 , n
174
- check := func (l int ) bool {
175
- i := 0
176
- for i+l-1 < n {
177
- j := i + l - 1
178
- if presum[j+1 ]-presum[i] <= maxCost {
246
+ check := func (x int ) bool {
247
+ for i := 0 ; i+x-1 < n; i++ {
248
+ if f[i+x]-f[i] <= maxCost {
179
249
return true
180
250
}
181
- i++
182
251
}
183
252
return false
184
253
}
185
- for left < right {
186
- mid := (left + right + 1 ) >> 1
254
+ l , r := 0 , n
255
+ for l < r {
256
+ mid := (l + r + 1 ) >> 1
187
257
if check (mid) {
188
- left = mid
258
+ l = mid
189
259
} else {
190
- right = mid - 1
260
+ r = mid - 1
261
+ }
262
+ }
263
+ return l
264
+ }
265
+
266
+ func abs (x int ) int {
267
+ if x < 0 {
268
+ return -x
269
+ }
270
+ return x
271
+ }
272
+ ```
273
+
274
+ ``` go
275
+ func equalSubstring (s string , t string , maxCost int ) (ans int ) {
276
+ var sum , j int
277
+ for i := range s {
278
+ sum += abs (int (s[i]) - int (t[i]))
279
+ for ; sum > maxCost; j++ {
280
+ sum -= abs (int (s[j]) - int (t[j]))
281
+ }
282
+ if ans < i-j+1 {
283
+ ans = i - j + 1
191
284
}
192
285
}
193
- return left
286
+ return
194
287
}
195
288
196
289
func abs (x int ) int {
197
- if x > 0 {
198
- return x
290
+ if x < 0 {
291
+ return - x
199
292
}
200
- return - x
293
+ return x
201
294
}
202
295
```
203
296
0 commit comments