467 words
2 minutes
力扣每日一题 20260223

1461. 检查一个字符串是否包含所有长度为 K 的二进制子串#

看了下数据范围感觉很宽,我们可以用暴力枚举的做法。

首先考虑长度为 kk0101 字符串有 2k2^k 种,所以我们可以枚举字符串 ss 的所有长度为 kk 的字串,丢到哈希表里,最后看哈希表里有没有 2k2^k 个元素就好了,复杂度 O((nk)k)O((n-k)k)

代码:

class Solution {
public:
bool hasAllCodes(string s, int k) {
if (s.size() < k) return false;
unordered_map<int, int> mp;
for (int i = 0; i <= s.size() - k; i++) {
int x = stoi(s.substr(i, k), nullptr, 2);
mp[x] = 1;
}
if (mp.size() == (1 << k)) return true;
else return false;
}
};

上面是最简单粗暴的做法,我们可以在循环里加一个剪枝,如果提前找到了 2k2^k 种子串就直接返回掉。

代码:

class Solution {
public:
bool hasAllCodes(string s, int k) {
if (s.size() < k) return false;
unordered_map<int, int> mp;
for (int i = 0; i <= s.size() - k; i++) {
int x = stoi(s.substr(i, k), nullptr, 2);
mp[x] = 1;
//这里喵↓
if (mp.size() == (1 << k)) return true;
}
if (mp.size() == (1 << k)) return true;
else return false;
}
};

再继续想,考虑到我们枚举每个子串是不是很像滑动窗口,那我们完全没必要用 O(k)O(k) 的复杂度去取子串,我们只需要在枚举下一个子串的时候减掉丢下去那位,加上新进来的那位(通过左右移就可以实现),这样我们能剩一个 O(k)O(k) 的复杂度,把复杂度降到 O(n)O(n)

代码:

class Solution {
public:
bool hasAllCodes(string s, int k) {
if (s.size() < k) return false;
int mask = (1 << k) - 1, x = 0;
unordered_map<int, int> mp;
for (int i = 0; i < s.size(); i++) {
x = (x << 1 & mask) | (s[i] & 1);
if (i + 1 >= k) mp[x] = 1;
if (mp.size() == (1 << k)) return true;
}
if (mp.size() == (1 << k)) return true;
else return false;
}
};
力扣每日一题 20260223
https://fuwari.vercel.app/posts/leetcode_daily/0223/
Author
P19E99
Published at
2026-02-23
License
CC BY-NC-SA 4.0