题目地址:
https://www.lintcode.com/problem/find-substring/description
给定一个长 n n n字符串 s s s,和一个正整数 k k k,找到 s s s中所有长度为 k k k并且无重复字母的子串(相等的子串只算一个)。返回这样的子串个数。题目保证只含英文小写字母。
直接截取所有长度 k k k的子串然后判一下是否无重复字母即可。至于子串的判重,可以用字符串哈希来优化,优化之后判重可以 O ( 1 ) O(1) O(1)时间内完成。代码如下:
import java.util.HashSet;
import java.util.Set;
public class Solution {
/**
* @param str: The string
* @param k: The length of the substring
* @return: The answer
*/
public int findSubstring(String str, int k) {
// Write your code here
if (k > str.length()) {
return 0;
}
long p = 131, hash = 0, pow = 1;
int[] count = new int[26];
// 算一下str[0 : k - 1]的哈希值,以及各个字符出现次数
for (int i = 0; i < k; i++) {
count[str.charAt(i) - 'a']++;
pow *= p;
hash = hash * p + str.charAt(i);
}
Set<Long> set = new HashSet<>();
if (check(count)) {
set.add(hash);
}
for (int i = k; i < str.length(); i++) {
hash = hash * p + str.charAt(i);
hash -= str.charAt(i - k) * pow;
count[str.charAt(i) - 'a']++;
count[str.charAt(i - k) - 'a']--;
if (check(count)) {
set.add(hash);
}
}
return set.size();
}
private boolean check(int[] count) {
for (int i = 0; i < 26; i++) {
if (count[i] > 1) {
return false;
}
}
return true;
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( n − k ) O(n-k) O(n−k)。