件名のソース:https://leetcode-cn.com/problems/get-equal-substrings-within-budget/
タイトル説明
同じ長さの2つの文字列sとtを与えます。
sのi番目の文字をtのi番目の文字に変更するには、| s [i] -t [i] |のオーバーヘッドが必要です(オーバーヘッドは0の場合があります)。これは、ASCIIコード値の違いです。 2文字の絶対値。
文字列を変更するための最大予算はmaxCostです。文字列を変換する場合、総コストは予算以下である必要があります。これは、文字列の変換が完了しない可能性があることも意味します。
sの部分文字列をtの対応する部分文字列に変換できる場合は、変換できる最大長を返します。
sに、tの対応する部分文字列に変換できる部分文字列がない場合、0が返されます。
示例 1:
输入:s = "abcd", t = "bcdf", cost = 3
输出:3
解释:s 中的 "abc" 可以变为 "bcd"。开销为 3,所以最大长度为 3。
示例 2:
输入:s = "abcd", t = "cdef", cost = 3
输出:1
解释:s 中的任一字符要想变成 t 中对应的字符,其开销都是 2。因此,最大长度为 1。
示例 3:
输入:s = "abcd", t = "acde", cost = 0
输出:1
解释:你无法作出任何改动,所以最大长度为 1。
提示:
1 <= s.length, t.length <= 10^5
0 <= maxCost <= 10^6
s 和 t 都只含小写英文字母。
一般的なアイデア
- 2つの文字列が与えられた場合、文字列内の文字をt(文字間の距離の絶対値)の対応する位置の文字に変換し、コストを与えて、変換できる最長の部分文字列の長さを見つけます
スライディングウィンドウ+デュアルポインター
- 文字間の距離はdif配列に格納され、スライディングウィンドウの右側のウィンドウがループ変数として使用されます。現在の文字を変更する必要がある場合は、現在の使用済みカウントが合計されます。今回は徐々に左ウィンドウを移動し、この時点で最長のウィンドウ長を更新します
const int MAXN = 1e5 + 1;
int diff[MAXN];
class Solution {
public:
int equalSubstring(string s, string t, int maxCost) {
int left = 0, right = 0, ans = 0;
int len = s.length();
memset(diff, 0, sizeof(diff));
for(int i = 0 ; i < len ; ++i) diff[i] = abs(s[i] - t[i]);
int curCost = 0;
for(; right < len ; ++right){
curCost += diff[right];
while(curCost > maxCost){
curCost -= diff[left];
++left;
}
ans = max(ans, right - left + 1);
}
return ans;
}
};
複雑さの分析
- 時間計算量:O(n)。nは配列の長さであり、左右両方がn回スライドしていると見なすことができます。
- スペースの複雑さ:O(n)。nは配列の長さです
プレフィックスと+二分探索
- 文字間の距離が格納されている配列はすべて正の数であるため、これは、接頭辞の合計のアイデアを使用して単調に増加するシーケンスを生成するように促し、バイナリ検索を直接実行できるようにします。O(logn)は最後を見つけます次の条件を満たすもの番号、および最長のウィンドウ長の合計を更新します
[バウンド]-バウンド[右-1]> =ターゲット合計[バウンド]-バウンド[右-1]> =ターゲットs u m s [ b o u n d ]−b o u n d [ r i g h t−1 ]>>=t a r g e t
class Solution {
public:
int equalSubstring(string s, string t, int maxCost) {
int left = 0, ans = 0, len = s.length();
int nums[len + 1];
memset(nums, 0, sizeof(nums));
for(int i = 1 ; i <= len ; ++i) nums[i] = nums[i - 1] + abs(s[i - 1] - t[i - 1]);
for(int right = 1; right <= len ; ++right){
int target = nums[right - 1] + maxCost;
int index = BinarySearch(target, nums, 0, len);
ans = max(ans, index - right + 1);
}
return ans;
}
int BinarySearch(int target, int* nums,int left, int right){
int len = right;
while(left <= right){
int mid = right + ((left - right) >> 1);
if(nums[mid] > target) right = mid - 1;
else{
if(mid == len || nums[mid + 1] > target) return mid;
else left = mid + 1;
}
}
return -1;
}
};
複雑さの分析
- 時間計算量:O(nlogn)。nは配列の長さ、nサイクル* lognはバイナリ検索の時間計算量です
- スペースの複雑さ:O(n)。nは配列の長さです