タイトル説明:
置換操作s
を実行する必要がある 文字列 (0 からインデックス付けされた) を取得します 。k
置換演算は 、長さ、 、 k
の 3 つの並列配列として指定されます。indices
sources
targets
最初の i
置換操作を完了するには、次の手順を実行します。
- 部分文字列が 元の文字列の インデックス に出現する
sources[i]
かどうかを 確認します 。s
indices[i]
- 存在しない場合は 何もしません 。
- 存在する場合は、
targets[i]
部分 文字列を に置き換えます。
たとえば s = "abcd"
、 indices[i] = 0
、 、 sources[i] = "ab"
、 の場合targets[i] = "eee"
、置換の結果は になります 。"eeecd"
すべての置換操作は 同時に実行する 必要があります。これは、置換操作が互いのインデックスに影響を与えてはならないことを意味します。テスト ケースでは、要素が重ならない ようにします。
- たとえば、 のテスト ケースは、 置換 と 重複する ため生成されませ
s = "abc"
ん 。indices = [0,1]
sources = ["ab","bc"]
"ab"
"bc"
ペアに対してすべての置換操作を実行した後の 結果の文字列s
を返します 。
部分文字列は 、文字列内の連続した文字のシーケンスです。
例 1:
入力: s = "abcd"、インデックス = [0,2]、ソース = ["a","cd"]、ターゲット = ["eee","ffff"] 出力: "eeebffff" 説明: " a " からs はインデックス 0 から始まるため、「eee」に置き換えられます。 「cd」は s のインデックス 2 から始まるため、「ffff」に置き換えられます。
例 2:
入力: s = "abcd"、インデックス = [0,2]、ソース = ["ab","ec"]、ターゲット = ["eee","ffff"] 出力: "eeecd" 説明: " ab " からs はインデックス 0 から始まるため、「eee」に置き換えられます。「ec」は元のS のインデックス 2 から始まっていないため、置換されません。
ヒント:
1 <= s.length <= 1000
k == indices.length == sources.length == targets.length
1 <= k <= 100
0 <= indices[i] < s.length
1 <= sources[i].length, targets[i].length <= 50
s
小文字の英字のみで構成されますsources[i]
targets[i]
小文字の英字のみで構成されてい ます
問題解決のアイデア:
方法 1: 添字 + シミュレーションによる並べ替え
アイデアとアルゴリズム
トピックの要件に従って直接シミュレーションできます。
まず、配列のインデックス\textit{indices} インデックスに従って、すべての置換操作を昇順に並べ替えます。このステップでは、indices\textit{indices}indices、sources\textit{sources}sources、targets\textit{targets}targets の 3 つの配列を同時に並べ替えることは困難です。長さを使用できます (mmm で示されます)。 ) と同じ配列 ops\textit{ops}ops は、000 から m−1m-1m−1 までの mmm 添字を格納し、ops\textit{ops}ops 自体の最初のキーとして indices\textit{indices}indices を使用します。単語を並べ替えることができます。
ソートが完了したら、指定された文字列 sss を走査して操作できます。別のポインター pt\textit{pt}pt を使用して、ops\textit{ops}ops の最初の要素を指し、実行される現在の操作を示します。iii 番目の文字に移動するときは、まず pt\textit{pt}pt を境界の外に出るまで右に移動し続けるか、ops[pt]\textit{ops}[\textit{pt}]ops[pt] ] 演算の添字は iii 以上です。この時点で、次の 2 つの状況が発生します。
添字が iii より大きい場合は、添字 iii を使用した演算は存在しないことを意味します。文字 iii を答えに直接入れることができます。
この添字が iii に等しい場合は、添字 iii を使用した操作があることを意味します。iii の位置から始まる sss の長さを、sources[ops[i]]\textit{sources}[\textit{ops}[i]]sources[ops[i]] およびsources[ops[i]] の部分文字列と比較します。 ] \textit{sources}[\textit{ops}[i]]sources[ops[i]] 比較用:
それらが等しい場合、置換操作は成功し、targets[ops[i]]\textit{targets}[\textit{ops}[i]]targets[ops[i]] を答えに入れます。置換操作は重複できないため、sources[ops[i]]\textit{sources}[\textit{ops}[i]]sources[ops[i]] length の文字数を直接スキップできます。
それ以外の場合、置換操作は失敗し、単純に文字 iii を答えに入力できます。
このタイトルは、成功した置換操作が重複しないことを保証するだけであり、失敗した置換操作が重複しないことを保証するものではないことに注意してください。したがって、この添え字が iii に等しい場合、複数の置換操作を試行する必要がある可能性があります。つまり、境界の外に出るまで ptptpt を右に移動するか、ops[pt]\textit{ops }[\textit{pt }]ops[pt] iii より厳密に大きい添え字を持つ ops。実行される置換操作は順番に試行する必要があります。そのうちの 1 つが成功すると、残りは試行する必要がなく、直接終了できます。
コード
class Solution {
public String findReplaceString(String s, int[] indices, String[] sources, String[] targets) {
//定义n,m分别代表s字符串的长度和索引数组的长度
int n = s.length(), m = indices.length;
//用ArrayList ops来保存indices,作为对应s字符串下标值
//利用ArrayList以便于排序等操作
List<Integer> ops = new ArrayList<>();
for (int i = 0; i < m; i++) {
ops.add(i);
}
//??
ops.sort((i, j) -> indices[i] - indices[j]);
//利用StringBuilder保存结果
StringBuilder ans = new StringBuilder();
//??
//>>>>>>>>>>>>>这是在准备下标值
int pt = 0;
for (int i = 0; i < n;) {
while (pt < m && indices[ops.get(pt)] < i) {
pt++;
}
//>>>>>>>>>>>>>>
//初始化查找结果标记
boolean succeed = false;
//遍历条件1:下标的限制条件
while (pt < m && indices[ops.get(pt)] == i) {
//遍历条件2:字符串比较的条件
if (s.substring(i, Math.min(i + sources[ops.get(pt)].length(), n)).equals(sources[ops.get(pt)])) {
//查找结果标记改变
succeed = true;
//相等则退出本次循环
break;
}
//循环下一个下标值
pt++;
}
//本次查找完成后对应的操作
if (succeed) {
//有匹配的:需要进行使用目标字符串替换被查找的字符串的对应的字符
ans.append(targets[ops.get(pt)]);
i += sources[ops.get(pt)].length();
} else {
//没有匹配的:直接追加到结果尾部
ans.append(s.charAt(i));
i++;
}
}
//返回结果字符串
return ans.toString();
}
}