Problem

Given a binary string s and an integer k, return true if every binary code of length k is a substring of s. Otherwise, return false.

Examples

Example 1:

1
2
3
4
5
Input:
s = "00110110", k = 2
Output:
 true
Explanation: The binary codes of length 2 are "00", "01", "10" and "11". They can be all found as substrings at indices 0, 1, 3 and 2 respectively.

Example 2:

1
2
3
4
5
Input:
s = "0110", k = 1
Output:
 true
Explanation: The binary codes of length 1 are "0" and "1", it is clear that both exist as a substring. 

Example 3:

1
2
3
4
5
Input:
s = "0110", k = 2
Output:
 false
Explanation: The binary code "00" is of length 2 and does not exist in the array.

Solution

Intuition

We need to check if every possible binary string of length k appears as a substring in s. There are exactly 2^k such binary codes. We can use a set to collect all unique substrings of length k in s and compare the size to 2^k.

Approach

  • Iterate over all substrings of length k in s and add them to a set.
  • If the set size equals 2^k, return true; otherwise, return false.
Python
1
2
3
4
class Solution:
    def hasAllCodes(self, s: str, k: int) -> bool:
        seen = set(s[i:i+k] for i in range(len(s)-k+1))
        return len(seen) == 1 << k
Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import java.util.*;
class Solution {
    public boolean hasAllCodes(String s, int k) {
        Set<String> set = new HashSet<>();
        for (int i = 0; i <= s.length() - k; i++) {
            set.add(s.substring(i, i + k));
        }
        return set.size() == (1 << k);
    }
}
C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <unordered_set>
#include <string>
using namespace std;
class Solution {
public:
    bool hasAllCodes(string s, int k) {
        unordered_set<string> seen;
        for (int i = 0; i + k <= s.size(); ++i)
            seen.insert(s.substr(i, k));
        return seen.size() == (1 << k);
    }
};
Go
1
2
3
4
5
6
7
func hasAllCodes(s string, k int) bool {
    seen := make(map[string]struct{})
    for i := 0; i <= len(s)-k; i++ {
        seen[s[i:i+k]] = struct{}{}
    }
    return len(seen) == 1<<k
}
Kotlin
1
2
3
4
5
6
7
8
9
class Solution {
    fun hasAllCodes(s: String, k: Int): Boolean {
        val set = mutableSetOf<String>()
        for (i in 0..s.length - k) {
            set.add(s.substring(i, i + k))
        }
        return set.size == (1 shl k)
    }
}
Rust
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
use std::collections::HashSet;
impl Solution {
    pub fn has_all_codes(s: String, k: i32) -> bool {
        let k = k as usize;
        let mut set = HashSet::new();
        let bytes = s.as_bytes();
        for i in 0..=bytes.len().saturating_sub(k) {
            set.insert(&bytes[i..i+k]);
        }
        set.len() == 1 << k
    }
}

Complexity

  • Time: O(n * k), where n = length of s
  • Space: O(2^k * k)

Method 2: Rolling Hash (Optimized for Large k)

Intuition

Instead of storing substrings, we can use a rolling hash to store integer representations of the binary codes.

Approach

  • Use a sliding window and bit manipulation to represent each substring as an integer.
  • Store each integer in a set.
  • Compare the set size to 2^k.
Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Solution:
    def hasAllCodes(self, s: str, k: int) -> bool:
        need = 1 << k
        got = set()
        hash_val = 0
        for i, c in enumerate(s):
            hash_val = ((hash_val << 1) & ((1 << k) - 1)) | int(c)
            if i >= k - 1:
                got.add(hash_val)
        return len(got) == need

Complexity

  • Time: O(n)
  • Space: O(2^k)

Method 3: Bitmask Optimization (Space Efficient, for Large k)

Intuition

If k is not too large (e.g., k <= 20), we can use a boolean array of size 2^k to track which binary codes have been seen, using bitmasking for fast lookup and update.

Approach

  • Initialize a boolean array of size 2^k.
  • Use a rolling bitmask to represent the current substring as an integer.
  • Mark the corresponding index as seen.
  • If all indices are seen, return true.
Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution:
    def hasAllCodes(self, s: str, k: int) -> bool:
        n = len(s)
        if n < k: return False
        total = 1 << k
        seen = [False] * total
        mask = 0
        for i in range(n):
            mask = ((mask << 1) & (total - 1)) | int(s[i])
            if i >= k - 1:
                seen[mask] = True
        return all(seen)
Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution {
    public boolean hasAllCodes(String s, int k) {
        int n = s.length(), total = 1 << k, mask = 0;
        boolean[] seen = new boolean[total];
        for (int i = 0; i < n; ++i) {
            mask = ((mask << 1) & (total - 1)) | (s.charAt(i) - '0');
            if (i >= k - 1) seen[mask] = true;
        }
        for (boolean b : seen) if (!b) return false;
        return true;
    }
}
C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <vector>
#include <string>
using namespace std;
class Solution {
public:
    bool hasAllCodes(string s, int k) {
        int n = s.size(), total = 1 << k, mask = 0;
        vector<bool> seen(total, false);
        for (int i = 0; i < n; ++i) {
            mask = ((mask << 1) & (total - 1)) | (s[i] - '0');
            if (i >= k - 1) seen[mask] = true;
        }
        for (bool b : seen) if (!b) return false;
        return true;
    }
};
Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func hasAllCodes(s string, k int) bool {
    n, total, mask := len(s), 1<<k, 0
    seen := make([]bool, total)
    for i := 0; i < n; i++ {
        mask = ((mask << 1) & (total - 1)) | int(s[i]-'0')
        if i >= k-1 {
            seen[mask] = true
        }
    }
    for _, b := range seen {
        if !b {
            return false
        }
    }
    return true
}
Kotlin
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Solution {
    fun hasAllCodes(s: String, k: Int): Boolean {
        val n = s.length
        val total = 1 shl k
        val seen = BooleanArray(total)
        var mask = 0
        for (i in 0 until n) {
            mask = ((mask shl 1) and (total - 1)) or (s[i] - '0')
            if (i >= k - 1) seen[mask] = true
        }
        return seen.all { it }
    }
}
Rust
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
impl Solution {
    pub fn has_all_codes(s: String, k: i32) -> bool {
        let n = s.len();
        let k = k as usize;
        let total = 1 << k;
        let mut seen = vec![false; total];
        let bytes = s.as_bytes();
        let mut mask = 0;
        for i in 0..n {
            mask = ((mask << 1) & (total - 1)) | (bytes[i] - b'0') as usize;
            if i + 1 >= k {
                seen[mask] = true;
            }
        }
        seen.iter().all(|&b| b)
    }
}

Complexity

  • Time: O(n)
  • Space: O(2^k)