1. 程式人生 > 其它 >LeetCode C++ 830. Positions of Large Groups【String】簡單

LeetCode C++ 830. Positions of Large Groups【String】簡單

技術標籤:字串演算法技巧-哨兵LeetCode

In a string sof lowercase letters, these letters form consecutive groups of the same character.

For example, a string like s = "abbxxxxzyy" has the groups "a", "bb", "xxxx", "z", and"yy".

A group is identified by an interval[start, end]

, wherestartandenddenote the start and endindices (inclusive) of the group. In the above example,"xxxx"has the interval[3,6].

A group is consideredlargeif it has 3 or more characters.

Returnthe intervals of every large group sorted inincreasing order by start index.

Example 1:

Input: s = "abbxxxxzzy"
Output: [[3,6]] Explanation: "xxxx" is the only large group with start index 3 and end index 6.

Example 2:

Input: s = "abc"
Output: []
Explanation: We have groups "a", "b", and "c", none of which are large groups.

Example 3:

Input: s = "abcdddeeeeaabbbcd"
Output: [[3,5],[6,9],[12,14]] Explanation: The large groups are "ddd", "eeee", and "bbb".

Example 4:

Input: s = "aba"
Output: [] 

Constraints:

  • 1 <= s.length <= 1000
  • s contains lower-case English letters only.

題意:在一個由小寫字母構成的字串 s 中,連續的相同字元被稱為一個分組,所有包含大於或等於三個連續字元的分組為較大分組。找到每一個較大分組的區間,按起始位置下標遞增順序排序後,返回結果。


解法 順序遍歷

一次順序掃描得到結果,需要處理最後一個可能的大分組。和行程長度壓縮演算法的寫法差不多:

class Solution {
public:
    vector<vector<int>> largeGroupPositions(string s) {
        vector<vector<int>> ans;
        int n = s.size();
        vector<int> temp{0, -1};
        for (int i = 1; i < n; ++i) {
            if (s[i] == s[i - 1]) temp[1] = i;
            else {
                if (temp[0] + 2 <= temp[1]) ans.push_back(temp);
                temp[0] = i; //temp[0]>temp[1]
            }
        }
        if (temp[0] + 2 <= temp[1]) ans.push_back(temp); //注意最後一個可能的大分組
        return ans;
    }
};

執行效率如下:

執行用時:0 ms, 在所有 C++ 提交中擊敗了100.00% 的使用者
記憶體消耗:7.6 MB, 在所有 C++ 提交中擊敗了46.77% 的使用者

另一個想法是使用哨兵,在原字串後面加一個大寫字母,就不用特殊處理連續字母在最後的情況了:

class Solution {
public:
    vector<vector<int>> largeGroupPositions(string s) {
        vector<vector<int>> ans;
        s.push_back('A'); //加一個大寫字母作為哨兵
        int n = s.size(), begin = 0;
        for (int i = 1; i < n; ++i) {
            if (s[i] != s[i - 1]) {
                if (i - begin >= 3) ans.push_back({begin, i - 1});
                begin = i;
            }
        } 
        return ans;
    }
};

執行效率如下:

執行用時:4 ms, 在所有 C++ 提交中擊敗了90.54% 的使用者
記憶體消耗:7.6 MB, 在所有 C++ 提交中擊敗了65.89% 的使用者

或者改為while迴圈,同樣不用處理最後的連續相同字元,程式碼還更短一點:

class Solution {
public:
    vector<vector<int>> largeGroupPositions(string s) {
        vector<vector<int>> ans;
        int n = s.size(), i = 0;
        while (i < n) {
            int j = i + 1;
            while (s[i] == s[j]) ++j; //掃描後續的連續相同字元
            if (j - i >= 3) ans.push_back({i, j - 1});
            i = j;
        } 
        return ans;
    }
};

執行效率如下:

執行用時:0 ms, 在所有 C++ 提交中擊敗了100.00% 的使用者
記憶體消耗:7.4 MB, 在所有 C++ 提交中擊敗了89.15% 的使用者