1. 程式人生 > >[leetcode]159. Longest Substring with At Most Two Distinct Characters

[leetcode]159. Longest Substring with At Most Two Distinct Characters

159. Longest Substring with At Most Two Distinct Characters.

1 暴力法

Time Limit Exceeded

class Solution(object):
    def lengthOfLongestSubstringTwoDistinct(self, s):
        """
        :type s: str
        :rtype: int
        """
        res = 0
        n = len(s)
        if n < 3: return n

        for i in range(n - 1):
            dic = {}
            dic[s[i]] = 1
            for j in range(i + 1, n):
                if s[j] not in dic:
                    dic[s[j]] = 1
                if len(dic) > 2:
                    break

                res = max(res, j - i + 1)
        return res

分析

我們每次遇到第三個字元的時候,都回到 i 並移一位,這種做法是不是可以優化呢?

我們來看個例子:1 1 1 2 1 1 1 1 2 1 1 2 3

我們訪問過第一個 1 之後,從第二個 1 開始,不可能比從第一個 1 開始搜尋得到的長度更長。

那從第一個 2 開始呢?

也是不可能的,因為它之後還有 1 ,到 3 的時候,還是要比第一個 1 得到的長度短。

那麼下一個下標從哪裡開始呢?

答案是,從第三個字元往前看,找到前一個字元,如果前面是一組連續的相同的字元(連續的 1 或者連續的 2 都可以)的開始的位置。
當然,在實現的時候,我們會記錄下來這個位置的前一位。下面看程式碼實現:

Python

class Solution(object):
    def lengthOfLongestSubstringTwoDistinct(self, s):
        """
        :type s: str
        :rtype: int
        """
        res = 0
        n = len(s)
        if n < 3: return n

        i = 1
        fc = 0 # begin of first char
        efc = 0 # end of first char
        sc = None

        while i < n:
            if s[fc] == s[i]: # if is the first character, continue
                efc = i
                i += 1
                continue

            if sc is None: # if is not the first character, and not found seconde character yet.
                sc = i
                i += 1
                continue

            if s[sc] == s[i]: # if is the second character
                sc = i
                i += 1
                continue

            res = max(res, i - fc) # a third character occurs, update the result.

            next_fc = min(efc, sc) + 1 # find the next first char.
            fc, efc, i = next_fc, next_fc, next_fc + 1 # update parameters.
            sc = None

        return max(res, i - fc) # in case, the longest substring in the end.

C

int lengthOfLongestSubstringTwoDistinct(char* s) {
    if (strcmp(s, "") == 0) return 0;
    int fc = 0;
    int efc = 0;
    int i = 1;
    int sc = -1;
    int res = 0;

    while (*(s + i) != '\0') {
        if (*(s + i) == *(s + fc)) {
            efc = i;
            i += 1;
            continue;
        }

        if ((sc == -1) | *(s + sc) == *(s + i)) {
            sc = i;
            i += 1;
            continue;
        }

        res = i - fc > res ? i - fc : res;

        int next_fc = 1 + (sc > efc ? efc : sc);

        fc = next_fc;
        efc = next_fc;
        sc = -1;
        i = next_fc + 1;
    }

    return i - fc > res ? i - fc : res;
}