340. Longest Substring with At Most K Distinct Characters

340. Longest Substring with At Most K Distinct Characters


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.

和159. Longest Substring with At Most Two Distinct Characters一样。

方法1: hash + index

思路:

用hashmap来维持每个字符出现的最后位置,当hash.size() < 2 时,可以直接加入。双指针right指向的位置如果是一个出现过的字符,可以直接更新该字符的最后坐标。反之如果是一个新的字符,而此时hash的size已经== 2,我们需要找到当前两个字符中最早结束的那个。怎么寻找呢?通过移动left,要意识到只有字母出现的最后一次满足hash[s[left]] == left。掌握了这一点,只要用一个内循环找到这个位置,删除left的字符,left再右移一位,就可以了。

易错点

  1. 如何识别“最早结束的字符”这一点不好想到,最后也别忘left++
  2. 不要忘了把right添加到hash里

Complexity

Time complexity: O(n)
Space complexity: O(1), hash始终不超过3个entry

class Solution {
public:
    int lengthOfLongestSubstringTwoDistinct(string s) {
        int result = 0;
        int left = 0;
        unordered_map<char, int> hash;
        for (int right = 0; right < s.size(); right++){
            // 还有余量
            if (hash.size() < 2){
                hash[s[right]] = right;
            }
            else {
                if (hash.count(s[right]) == 0){
                    hash[s[right]] = right;
                    while (hash[s[left]] != left) left ++;
                    hash.erase(s[left]);
                    left ++;
                }
                else {
                    hash[s[right]] = right;
                }
            }
            result = max(result, right - left + 1);
        }
        return result;
        
    }
};

方法2: hash + count

grandyang: http://www.cnblogs.com/grandyang/p/5185561.html
思路:

这种方法和上面的区别是,并不记录index,而是对每个字符计数。那么左指针在舍弃左边的时候就需要依次将hash值–,这里循环条件也相对与上面被精简:先无脑推入新的字符,如果多出来了再去掉,而内循环中只要erase这一步还没有发生,left就会一直向右移动。

Complexity

Time complexity: O(n)
Space complexity: O(1)

class Solution {
public:
    int lengthOfLongestSubstringKDistinct(string s, int k) {
        if (k == 0) return 0;
        int result = 0;
        unordered_map<char, int> hash;
        
        int left = 0;
        for (int right = 0; right < s.size(); right++){
            ++hash[s[right]];
            while(hash.size() > k){
                if (--hash[s[left]] == 0) hash.erase(s[left]);
                left++;
            }
            result = max(result, right - left + 1);
        }
        return result;
    }
};
             
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值