[LeetCode] Find And Replace in String 在字符串中查找和替換

 

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

  1. 0 <= indexes.length = sources.length = targets.length <= 100
  2. 0 < indexes[i] < S.length <= 1000
  3. All characters in given inputs are lowercase letters.

 

這道題給了咱們一個字符串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

https://leetcode.com/problems/find-and-replace-in-string/discuss/130577/C%2B%2B-5-lines-6-ms-bucket-sort-O(n)

https://leetcode.com/problems/find-and-replace-in-string/discuss/130587/C%2B%2BJavaPython-Replace-S-from-right-to-left

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索