159. Longest Substring with At Most Two Distinct Characters

题目:

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.

链接: http://leetcode.com/problems/longest-substring-with-at-most-two-distinct-characters/

题解:

跟"Longest Substring Without Repeating Characters"很像。碰到这种题目依然是考虑使用Sliding Window来解决,只不过要多考虑用什么样的数据结构来存储数据。

这里有几种方法,第一种是用HashSet<Character>来保存字符,从头到尾扫描字符串,当set.size() >= 2并且当前字符为新字符,我们从当前字符的前一个字符s.charAt(i - 1)从后向前查找,碰到不同于s.charAt(i - 1)的字符在位置j时,设置index为j + 1,尝试更新max。假如要扩展到n个distinct characters的话,我们就需要另外设置一个counter,来记录反向查找时一种经历了多少种字符。

Time Complexity - O(n), Space Complexity - O(1)

public class Solution {
    public int lengthOfLongestSubstringTwoDistinct(String s) {      //sliding window
        if(s == null || s.length() < 3)
            return s.length();
        
        Set<Character> set = new HashSet<>();
        int max = 0, index = 0;                                 // use index to record left bar of window
        
        for(int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if(!set.contains(c)) {
                if(set.size() >= 2) {
                    for(int j = i - 1; j >= 0; j--)             // scan from i - 1 to 0
                        if(s.charAt(j) != s.charAt(i - 1)) {
                            set.remove(s.charAt(j));
                            index = j + 1;
                            break;
                        }
                } 
                set.add(c);
            }
            max = Math.max(i - index + 1, max);
        }
        
        return max;
    }
}

第二种可以用HashMap<Character,Integer>来存储字符以及字符最后一次出现的lastIndex。这样碰到map.size() >= 2而且要添加新字符的时候,我们只需要查找到map.keySet里不同于上一字符s.charAt(i - 1)的那个entry,设置index为entry.val + 1即可,接下来继续尝试更新max。 max与第一种方法一样,为Math.max(i - index + 1, max)。扩展到n个distinct character的话,要对lastIndex做个排序,然后按照倒序找到需要溢出的字符,设置index,再更新max。

Time Complexity - O(n),Space Complexity - O(1)。

public class Solution {
    public int lengthOfLongestSubstringTwoDistinct(String s) {      //sliding window
        if(s == null || s.length() < 3)
            return s.length();
        HashMap<Character, Integer> map = new HashMap<>();       // use map to record <Character char, Integer lastIndex>
        int max = 0, index = 0;                                 // use index to record left bar of window
        
        for(int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if(!map.containsKey(c)) {
                if(map.size() >= 2) {
                    Set<Character> keys = map.keySet();
                    
                    for(Character key : keys)               // find char different from lastChar
                        if(key != s.charAt(i - 1)) {
                            index = map.get(key) + 1;
                            map.remove(key);
                            break;
                        }
                } 
            }
            map.put(c, i);
            max = Math.max(i - index + 1, max);
        }
        
        return max;
    }
}

第三种可以不用Set以及Map来存储,反正只要求两个不同字符,可以设置几个变量,也能有一样的效果。

Reference:

https://leetcode.com/discuss/19261/my-java-ac-solution

https://leetcode.com/discuss/21929/share-my-c-solution

https://leetcode.com/discuss/22980/java-solution-for-k-unique-characters

https://leetcode.com/discuss/31292/clean-11-lines-ac-answer-o-1-space-o-n-time

https://leetcode.com/discuss/54294/java-sliding-window-solution-fast

原文地址:https://www.cnblogs.com/yrbbest/p/4489714.html