题目
你会得到一个字符串 s
(索引从 0 开始),你必须对它执行 k
个替换操作。替换操作以三个长度均为 k
的并行数组给出: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", indices = [0,2], sources = ["a","cd"], targets = ["eee","ffff"]
输出: "eeebffff"
解释: "a" 从 s 中的索引 0 开始,所以它被替换为 "eee"。
"cd" 从 s 中的索引 2 开始,所以它被替换为 "ffff"。
示例 2:
输入: s = "abcd", indices = [0,2], sources = ["ab","ec"], targets = ["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]
仅由小写英文字母组成
题解
- 设
s
长度为n
, 创建一个长度 为n
的replace
列表 - 遍历
indices
数组,如果字符串s
从indices[i]
位置开始的sources[i]
子串相同,则记录下s
中替换的位置和对应替换数组中的位置replace[indices[i]] = i
; - 声明
res = []
遍历字符串s
, 初始化i = 0
, 如果replace[i]
不存在,那么表示无需替换,把s[i]
添加到res
, 然后移动到下一个字符i++
, 如果replace[i]
不为空,那么把targets[replace[i]]
加入到答案,然后跳过当前对应的source[i]
的字符串即i += sources[replace[i]].length
复杂度分析
时间复杂度: O(n + ml)
, 其中 n
是字符串 s
的长度, m
是数组的indices
的长度, l
是数组 sources
和 targets
的平均长度
空间复杂度:O(n + ml)
, 哈希表需要的空间为O(m)
, 在替换操作中进行比较时,如果使用的语言支持无拷贝的切片操作,那么需要空间为O(1)
, 否则需要O(n + ml)
的辅助空间
代码
const n = s.length;
const replaces = new Array(n).fill(-1);
for (let k = 0; k < indices.length; k++) {
const [i, src] = [indices[k], sources[k]];
if (s.startsWith(src, i)) {
replaces[i] = k;
}
}
const ans = [];
for (let i = 0; i < n; ) {
if (replaces[i] >= 0) {
ans.push(targets[replaces[i]]);
i += sources[replaces[i]].length;
} else {
ans.push(s[i]);
i++;
}
}
return ans.join('');