To some string S
, we will perform some replacement operations that replace groups of letters with new ones (not necessarily the same size).html
Each replacement operation has 3
parameters: a starting index i
, a source word x
and a target word y
. The rule is that if x
starts at position i
in the original string S
, then we will replace that occurrence of x
with y
. If not, we do nothing.数组
For example, if we have S = "abcd"
and we have some replacement operation i = 2, x = "cd", y = "ffff"
, then because "cd"
starts at position 2
in the original string S
, we will replace it with "ffff"
.函数
Using another example on S = "abcd"
, if we have both the replacement operation i = 0, x = "ab", y = "eee"
, as well as another replacement operation i = 2, x = "ec", y = "ffff"
, this second operation does nothing because in the original string S[2] = 'c'
, which doesn't match x[0] = 'e'
.post
All these operations occur simultaneously. It's guaranteed that there won't be any overlap in replacement: for example, S = "abc", indexes = [0, 1], sources = ["ab","bc"]
is not a valid test case.this
Example 1:url
Input: S = "abcd", indexes = [0,2], sources = ["a","cd"], targets = ["eee","ffff"] Output: "eeebffff" Explanation: "a" starts at index 0 in S, so it's replaced by "eee". "cd" starts at index 2 in S, so it's replaced by "ffff".
Example 2:spa
Input: S = "abcd", indexes = [0,2], sources = ["ab","ec"], targets = ["eee","ffff"] Output: "eeecd" Explanation: "ab" starts at index 0 in S, so it's replaced by "eee". "ec" doesn't starts at index 2 in the original S, so we do nothing.
Notes:code
0 <= indexes.length = sources.length = targets.length <= 100
0 < indexes[i] < S.length <= 1000
这道题给了咱们一个字符串S,并给了一个坐标数组,还有一个源字符串数组,还有目标字符串数组,意思是若某个坐标位置起,源字符串数组中对应位置的字符串出现了,将其替换为目标字符串。题目真的是好长,但好在给了两个例子能够帮助咱们很好的理解题意。此题的核心操做就两个,查找和替换,须要注意的是,因为替换操做会改变原字符串,可是咱们查找始终是基于最初始的S,好比例子2中,当完成了第一次替换后,S变为了 "eeecd",好像此时 "ec" 出现了,但仍然不能替换,由于一切查找都是基于最原始的那个S。那么正向的替换可能会产生这样的问题,咱们注意到题目中有个限制条件,就是说不会有重叠产生,好比 "abc",若是让在0位置上查找 "ab" 了,就不会让在1位置上查找 "bc",这样的话,其实咱们能够从后往前开始查找替换,由于不会有重叠,因此后面替换了的字符不会影响到前面。首先咱们须要给indexes数组排个序,由于可能不是有序的,可是却不能直接排序,这样会丢失和sources,targets数组的对应关系,这很麻烦。因此咱们新建了一个保存pair对儿的数组,将indexes数组中的数字跟其位置坐标组成pair对儿,加入新数组v中,而后给这个新数组按从大到小的方式排序,这样咱们既排了序,又保存了对应关系,岂不美哉!orm
下面就要开始遍历新数组v了,对于遍历到的pair对儿,取出第一个数字,保存到i,表示S中须要查找的位置,取出第二个数字,而后根据这个位置分别到sources和targets数组中取出源字符串和目标字符串,而后咱们在S中的i位置,向后取出和源字符串长度相同的子串,而后比较,若正好和源字符串相等,则将其替换为目标字符串便可,参见代码以下:htm
解法一:
class Solution { public: string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) { vector<pair<int, int>> v; for (int i = 0; i < indexes.size(); ++i) { v.push_back({indexes[i], i}); } sort(v.rbegin(), v.rend()); for (auto a : v) { int i = a.first; string s = sources[a.second], t = targets[a.second]; if (S.substr(i, s.size()) == s) { S = S.substr(0, i) + t + S.substr(i + s.size()); } } return S; } };
咱们也可使用TreeMap来代替须要排序的数组,因为TreeMap默认的是最小堆,而咱们须要的是最大堆,只要在定义上加一个greater就好了,其余部分基本没有任何的区别,参见代码以下:
解法二:
class Solution { public: string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) { map<int, int, greater<int>> m; for (int i = 0; i < indexes.size(); ++i) { m[indexes[i]] = i; } for (auto a : m) { int i = a.first; string s = sources[a.second], t = targets[a.second]; if (S.substr(i, s.size()) == s) { S = S.substr(0, i) + t + S.substr(i + s.size()); } } return S; } };
再来看一种稍有不一样的解法,以前的两种解法都是直接在S上替换,这里咱们新建一个结果res字符串,这里仍是使用HashMap来保存映射对,可是稍有不一样的是,咱们并非无脑的添加全部的映射对儿,而是先作个check,只要当发现能够查找到源字符串位置的时候,才添加映射对儿,这样就排除了全部不能替换的状况。而后咱们遍历原字符串S,对于每一个遍历到的位置,咱们都到HashMap中查找,若是发现须要替换,咱们就把目标字符串提取出来,加入结果res中,注意此时i也须要加上源字符串的长度。若不须要替换,则直接将字符加入结果res中,而后i移动到下一个位置,参见代码以下:
解法三:
class Solution { public: string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) { string res = ""; unordered_map<int, int> m; for (int i = 0; i < indexes.size(); ++i) { if (S.substr(indexes[i], sources[i].size()) == sources[i]) { m[indexes[i]] = i; } } for (int i = 0; i < S.size();) { if (m.count(i)) { res += targets[m[i]]; i += sources[m[i]].size(); } else { res.push_back(S[i]); ++i; } } return res; } };
咱们也可使用STL自带的replace函数来完成替换操做,有点偷懒啊~
解法四:
class Solution { public: string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) { map<int, pair<int, string>, greater<int>> m; for (int i = 0; i < indexes.size(); ++i) { if (S.substr(indexes[i], sources[i].size()) == sources[i]) { m[indexes[i]] = {sources[i].size(), targets[i]}; } } for (auto a : m) { S.replace(a.first, a.second.first, a.second.second); } return S; } };
参考资料:
https://leetcode.com/problems/find-and-replace-in-string/
https://leetcode.com/problems/find-and-replace-in-string/discuss/134758/Java-O(n)-solution