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