LeetCode 1461. 检查一个字符串是否包含所有长度为 K 的二进制子串
题目描述
给你一个二进制字符串 s 和一个整数 k。如果所有长度为 k 的二进制字符串都是 s 的子串,请返回 true,否则返回 false。
示例
输入:s = "00110110", k = 2
输出:true
解释:长度为 2 的二进制串有 "00"、"01"、"10"、"11",它们都在 s 中出现过。
解法一:哈希集合存储子串
思路
长度为 k 的二进制子串一共有 2^k 种可能。我们只需要将字符串 s 中所有长度为 k 的子串存入一个哈希集合,最后判断集合大小是否等于 2^k 即可。
剪枝优化
如果字符串的长度连理论上的最小长度都不够,那么肯定无法包含所有子串。包含所有 2^k 个二进制串的最短字符串长度是 (1 << k) + k - 1(即 de Bruijn 序列的长度)。因此可以先检查长度,快速返回 false。
代码实现
class Solution {
public:
bool hasAllCodes(string s, int k) {
// 长度预判断
if(s.size() < (1 << k) + k - 1) return false;
unordered_set<string> strs;
for(int i = 0; i + k <= s.size(); ++i) {
// 截取长度为 k 的子串并插入集合
strs.insert(s.substr(i, k));
}
return strs.size() == (1 << k);
}
};
复杂度分析
- 时间复杂度:O(n·k),其中 n 是字符串长度。需要遍历 O(n) 个子串,每次截取子串和计算哈希需要 O(k) 时间。
- 空间复杂度:O(2^k·k),哈希集合中最多存储
2^k个长度为 k 的字符串。

