day124 1016. 子串能表示从 1 到 N 数字的二进制串(Java)

118 阅读2分钟

题目来源: 1016. 子串能表示从 1 到 N 数字的二进制串

题目描述:

  • 描述: 给定一个二进制字符串 s 和一个正整数 n,如果对于 [1, n] 范围内的每个整数,其二进制表示都是 s 的 子字符串 ,就返回 true,否则返回 false 。 子字符串 是字符串中连续的字符序列。

  • 示例:

示例1:
输入:s = "0110", n = 3
输出:true
示例2:
输入:s = "0110", n = 4
输出:false

思路

思路1 题目给定一个二进制字符串s 和一个正整数n。我们需要判断1 到n 中的每一个整数是否都是s 的子字符串。

设[l,r] 表示大于等于l 且小于等于r 范围内的整数,对于n>1,一定存在kN+k∈N^+,使得2kn<2k+12^k≤n<2^{k+1}。那么对于[2k1,2k1][2^{k−1},2^k−1]内的数,它们都小于n,且二进制表示都为k 位,所以字符串s 中至少需要有2k12^{k−1}个长度为k 的不同二进制数。记字符串s 的长度为m,则m 至少需要满足:m2k1+k1m≥2^{k−1}+k−1 同理在[2k,n] 内的数,二进制表示都为k+1 位,所以m 同样需要满足:mn2k+k+1m≥n-2^k+k+1

若上述两个条件不满足,则可以直接返回False,否则,因为题目给定m≤1000,所以此时k 一定不大于11。又因为若s 的子串能包含[2k1,2k1][2^{k−1},2^k−1]全部二进制表示,则一定可以包含[1,2k1][1,2^{k−1}] 全部二进制表示。因为我们可以将[2k1,2k1][2^{k−1},2^k−1]中数的二进制表示中的最高位的1 去掉并去掉对应的前导零,便可以得到[0,2k11][0,2^{k−1}−1] 的全部二进制表示。

所以我们对字符串s 判断是否存在[2k1,2k1][2^{k−1},2^k−1][2k,n][2^k,n]的全部二进制表示即可。我们可以分别用长度为k 和k+1 的「滑动窗口」来枚举s 中全部长度为k 和k+1 的子串,将其加入哈希表,并判断哈希表中是否存在[2k1,n][2^{k-1},n]中的全部数即可

以上的分析都在n>1 的基础上,当n=1 时,我们只需要判断‘1’ 是否在s 中即可。

具体实现1

class Solution {
    public boolean queryString(String s, int n) {
        if (n == 1) {
            return s.indexOf('1') != -1;
        }
        int k = 30;
        while ((1 << k) >= n) {
            --k;
        }
        if (s.length() < (1 << (k - 1)) + k - 1 || s.length() < n - (1 << k) + k + 1) {
            return false;
        }
        return help(s, k, 1 << (k - 1), (1 << k) - 1) && help(s, k + 1, 1 << k, n);
    }

    public boolean help(String s, int k, int mi, int ma) {
        Set<Integer> set = new HashSet<Integer>();
        int t = 0;
        for (int r = 0; r < s.length(); ++r) {
            t = t * 2 + (s.charAt(r) - '0');
            if (r >= k) {
                t -= (s.charAt(r - k) - '0') << k;
            }
            if (r >= k - 1 && t >= mi && t <= ma) {
                set.add(t);
            }
        }
        return set.size() == ma - mi + 1;
    }
}

复杂度分析1:

  • 时间复杂度:O(logn+m),其中m 为字符串s 的长度。k 的求解时间开销为O(logn),「滑动窗口」枚举字符串s 每一个k 和k+1 子串的时间开销为O(m)。

  • 空间复杂度:O(m),其中m 为字符串s 的长度,主要为哈希表的空间开销。