1. 程式人生 > >340. Longest Substring with At Most K Distinct Characters

340. Longest Substring with At Most K Distinct Characters

Description

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

Example 1:

Input: s = “eceba”, k = 2
Output: 3
Explanation: T is “ece” which its length is 3.
Example 2:

Input: s = “aa”, k = 1
Output: 2
Explanation: T is “aa” which its length is 2.

Problem URL


Solution

給一個String,找到只能有k個字元組成的最長的子序列的長度。

Approach 1: Sliding window. Maintain a sliding window with size k to get the max length. Using a int array to store the frequency of each character in s. Then j is the fast pointer in the right, I is the slow pointer in the left, count is the number of characters current used. If map do not contain this word, store its frequence and count++; If we have more than k words,

class Solution {
    public int lengthOfLongestSubstringKDistinct(String s, int k) {
        int[] map = new int[256];
        int i = 0, count = 0, res = 0;
        for (int j = 0; j < s.length(); j++){
            if (map[s.charAt(j)]++ == 0){
                count++;
            }
            while
(count > k){ if (--map[s.charAt(i++)] == 0){ count--; } } res = Math.max(res, j - i + 1); } return res; } }

more readable solution

public int lengthOfLongestSubstringKDistinct(String s, int k) {
        int[] bits = new int[256];
        int max = 0, index = 0;
        int count = 0;
        for(int i = 0; i < s.length(); i++) {
            if(bits[s.charAt(i)] == 0) {
                count++;
            }
            bits[s.charAt(i)]++;
            while(count > k) {    // count > k delete char from the substring
                bits[s.charAt(index)]--;
                if(bits[s.charAt(index)] == 0) {
                    count--;
                }
                index++;
            }
            max = Math.max(max, i - index + 1);
        }
        return max;
    }

Time Complexity: O(n)
Space Complexity: O(256)

Approach 2: Using tree map to store the last occurance. But it is slower.

Code

class Solution {
    public int lengthOfLongestSubstringKDistinct(String s, int k) {
        if (s == null || s.isEmpty() || k == 0){
            return 0;
        }
        //lastOccurance stores the last show of index i's character
        TreeMap<Integer, Character> lastOccurance = new TreeMap<>();
        //inWindow stores the char and the index of current window.
        Map<Character, Integer> inWindow = new HashMap<>();
        int i = 0; 
        int res = 1;
        for (int j = 0; j < s.length(); j++){
            char in = s.charAt(j);
            //get new input char and if exceed window size, remove it.
            while (inWindow.size() == k && !inWindow.containsKey(in)){
                int first = lastOccurance.firstKey();
                char out = lastOccurance.get(first);
                inWindow.remove(out);
                lastOccurance.remove(first);
                i = first + 1;
            }
            //update or add new char in two maps.
            if (inWindow.containsKey(in)){
                lastOccurance.remove(inWindow.get(in));
            }
            inWindow.put(in, j);
            lastOccurance.put(j, in);
            res = Math.max(res, j - i + 1);
        }
        return res;
    }
}

Time Complexity: O(nlogk)
Space Complexity: O(k)


Review