【Lintcode】386. Longest Substring with At Most K Distinct Characters

题目地址:

https://www.lintcode.com/problem/longest-substring-with-at-most-k-distinct-characters/description

给定一个字符串 s s s,和一个整数 k k k,求 s s s中最多只含 k k k个不同字符的最长子串的长度。

思路是快慢双指针。我们先考虑暴力做法是怎样的,一定是形如:

for (int i = 0; i < s.length(); i++) {
	for (int j = i; j < s.length(); j++) {
		if (check...) {
			continue;
		} else {
			break;
		}
	}
}

也即,当发现满足条件的时候,就去扩大区间,否则右移左端点。当i++加完之后,我们发现j是不用回退的,因为在内层循环退出的时候,j所在的位置刚好不满足条件,之前都是满足条件的,所以可以直接用while循环来移动i指针,直到满足条件为止,再去右移j。所以思路就是,用一个数组维护当前区间内的每个字符出现的次数(这个数组实际上是当成哈希表来用的,长度是256)。当当前维护的区间满足条件,则扩展右边界(显然左指针右移不会产生更优解),否则右移左指针缩小区间。代码如下:

public class Solution {
    /**
     * @param s: A string
     * @param k: An integer
     * @return: An integer
     */
    public int lengthOfLongestSubstringKDistinct(String s, int k) {
        // write your code here
        int[] count = new int[256];
        
        int res = 0;
        for (int i = 0, j = 0; j < s.length(); j++) {
            count[s.charAt(j)]++;
            // 如果当前维护的区间不满足条件,则说明字符种类太多了,则右移左指针
            while (i <= j && !check(count, k)) {
                count[s.charAt(i)]--;
                i++;
            }
            
            // 此时如果满足条件了,则更新答案,否则说明i = j + 1,则右移j,继续遍历
            res = Math.max(res, j - i + 1);
        }
        
        return res;
    }
    
    private boolean check(int[] count, int k) {
        int c = 0;
        for (int i = 0; i < 256; i++) {
            if (count[i] > 0) {
                c++;
            }
        }
        
        return c <= k;
    }
}

时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)

©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页