159. Longest Substring with At Most Two Distinct Characters (Hard)

Given a string, find the length of the longest substring T that contains at most 2 distinct characters.

For example, Given s = “eceba”,

T is "ece" which its length is 3.

Solution 1: Hash Table 13ms

这道题给我们一个字符串,让我们求最多有两个不同字符的最长子串。那么我们首先想到的是用哈希表来做,哈希表记录每个字符的出现次数,然后如果哈希表中的映射数量超过两个的时候,我们需要删掉一个映射,比如此时哈希表中e有2个,c有1个,此时把b也存入了哈希表,那么就有三对映射了,这时我们的left是0,先从e开始,映射值减1,此时e还有1个,不删除,left自增1。这是哈希表里还有三对映射,此时left是1,那么到c了,映射值减1,此时e映射为0,将e从哈希表中删除,left自增1,然后我们更新结果为i - left + 1,以此类推直至遍历完整个字符串,参见代码如下:

class Solution {
public:
    int lengthOfLongestSubstringTwoDistinct(string s) {
        unordered_map<char, int> m;
        int start = 0, res = 0;
        for (int i = 0; i < s.size(); ++i) {
            ++m[s[i]];
            // discint k has been reached, cannot add new characters
            while (m.size() > 2) {
                // remove the one char in current substring
                if (--m[s[start]] == 0) m.erase(s[start]);
                ++start;
            }
            res = max(res, i-start+1);
        }

        return res;
    }
};

Solution 2: Hash Table 13ms

我们除了用哈希表来映射字符出现的个数,我们还可以映射每个字符最新的坐标,比如题目中的例子"eceba",遇到第一个e,映射其坐标0,遇到c,映射其坐标1,遇到第二个e时,映射其坐标2,当遇到b时,映射其坐标3,每次我们都判断当前哈希表中的映射数,如果大于2的时候,那么我们需要删掉一个映射,我们还是从left=0时开始向右找,我们看每个字符在哈希表中的映射值是否等于当前坐标left,比如第一个e,哈希表此时映射值为2,不等于left的0,那么left自增1,遇到c的时候,哈希表中c的映射值是1,和此时的left相同,那么我们把c删掉,left自增1,再更新结果,以此类推直至遍历完整个字符串,参见代码如下:

int lengthOfLongestSubstringTwoDistinct(string s) {
    int res = 0, start = 0;
    unordered_map<char, int> m;
    for (int i = 0; i < s.size(); ++i) {
        m[s[i]] = i;
        while (m.size() > 2) {
            if (m[s[start]] == start) {
                m.erase(s[start]);
            }
            ++start;
        }
        res = max(res, i-start+1);
    }
    return res;
}

Solution 3: Two Pointers 3ms

i: always points to the start of substring

j: points to the last occurrence of the 1st character.

If we have encountered 2 distinct characters and then see 3rd new character, we need to check if the 1st and 3rd characters are the same. If not, we move i to j+1 (now becomes the first char). If yes, not need to change.

Then move j to the last occurrence of 2nd character.

int lengthOfLongestSubstringTwoDistinct(string s) {
    int i = 0, j = -1, res = 0;
    for (int k = 1; k < s.size(); ++k) {
        if (s[k] == s[k-1]) continue;
        if (j > -1 && s[k] != s[j]) {
            res = max(res, k-i);
            i = j+1;
        }
        j = k-1;
    }
    return max(res, (int)s.size()-i);
}

Solution 4: Hash Table, Two Pointers 3ms

Substring problem template

class Solution {
public:
    int lengthOfLongestSubstringTwoDistinct(string s) {
        vector<int> map(128, 0);
        int count = 0, left = 0, right = 0, len = 0;
        while (right < s.size()) {
            if (map[s[right++]]++ == 0) ++count;
            while (count > 2) {
                if (--map[s[left++]] == 0) --count;
            }
            len = max(len, right-left);
        }
        return len;
    }
};

results matching ""

    No results matching ""