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

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

子字符串 是字符串中连续的字符序列。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-string-with-substrings-representing-1-to-n
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

class Solution {
    /**
     * 2^k <= n <= 2^(k+1)
     * [2^(k-1), 2^k-1]
     * [2^k, n]
     * <p>
     * 比如k=5
     * 2^(k-1)
     * 10000
     * 2^k-1
     * 11111
     * 2^k
     * 100000
     * 可见[2^(k-1), 2^k-1]包含[0, 2^k-1]
     * <p>
     * 设s的长度为m,则
     * m >= 2^(k-1) + k
     * m >= n - 2^k + 1 + k
     */

    public boolean queryString(String s, int n) {
        if (n == 1) {
            return s.contains("1");
        }
        int k = 30;
        while ((1 << k) > n) {
            k--;
        }
        int m = s.length();
        if (!((m >= (1 << (k - 1)) + k - 1) && (m >= n - (1 << k) + k + 1))) {
            return false;
        }
        return help(s, k, (1 << (k - 1)), (1 << k) - 1) && help(s, k + 1, (1 << k), n);
    }

    private boolean help(String s, int k, int lower, int upper) {
        Set<Integer> set = new HashSet<>();
        int sum = 0;
        for (int i = 0; i < s.length(); i++) {
            sum = sum * 2 + (s.charAt(i) - '0');
            if (i >= k - 1) {
                if (sum >= lower && sum <= upper) {
                    set.add(sum);
                }
                sum -= ((s.charAt(i - k + 1) - '0') << (k - 1));
            }
        }

        return set.size() == (upper - lower + 1);
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            System.out.println(new Solution().queryString(in.next(), in.nextInt()));
        }
    }
}
posted @ 2023-05-12 10:37  Tianyiya  阅读(17)  评论(0)    收藏  举报