LC.P1016[子串能表示从1到N数字的二进制串]
方法一:暴力
1 2 3 4 5 6 7 8
| class Solution { public boolean queryString(String s, int n) { for (int i = 1; i <= n; ++i) { if (!s.contains(Integer.toBinaryString(i))) return false; } return true; } }
|
- 时间复杂度:$O(min(m,n) \times mlogmin(m,n))$,其中$m$为s的长度。
- 空间复杂度:$O(logn)$
方法二:数学+滑动窗口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Solution { public boolean queryString(String s, int n) { if (n == 1) return s.contains("1"); int k = 31 - Integer.numberOfLeadingZeros(n); if (s.length() < Math.max(n - (1 << k) + k + 1, (1 << k - 1) + k + 1)) { return false; } return check(s, k, n / 2 + 1, (1 << k) - 1) && check(s, k + 1, 1 << k, n); }
private boolean check(String s, int k, int low, int high) { if (low > high) return true; Set<Integer> visited = new HashSet<>(); int mask = (1 << (k - 1)) - 1; int x = Integer.parseInt(s.substring(0, k - 1), 2), m = s.length(); for (int i = k - 1; i < m; ++i) { x = ((x & mask) << 1) | (s.charAt(i) - '0'); if (low <= x && x <= high) visited.add(x); } return visited.size() == high - low + 1; } }
|
- 时间复杂度:$O(m)$
- 空间复杂度:$O(min(m,n))$