leetcode 1461. Check If a String Contains All Binary Codes of Size K

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.

Example 1:

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:

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.

给一个字符串s, 长度k,
问s是否包含长度k的全部二进制数字。
比如k=2, 那么长度为2的全部二进制数字为00, 01, 10, 11, 那么s里面要含有这4个子字符串。

思路
方法1:
最容易想到的,长度为k的二进制数字一共有2k个,
那么把s中所有长度为k的子字符串都装入hashSet中,由于set中的元素是不重复的,只需要判断最后hashSet的size是否为2k即可。

public boolean hasAllCodes(String s, int k) {
    HashSet<String> set = new HashSet<>();
    int n = s.length();
    
    for(int i = 0; i <= n - k; i ++) {
        set.add(s.substring(i, i+k));
    }
    return set.size() == Math.pow(2, k);
}

方法2:
沿用上面的hashSet思想,但是这次不用hash set, 而只用到hash value来表示不重复的元素。
这里有一个技巧,就是bit 移位,
00左移一位 | 1 = 01, 01左移一位 | 0 = 10,依次类推,
我们需要做的是移位以后控制只取最后k位。

然后记录这个二进制数字,也就是hash val是否出现过,用一个boolean数组记录。
这也就是代码中hashVal = ((hashVal << 1) & allOne) | (s.charAt(i) - ‘0’);的意义。

当数字个数达到2k时,说明满足,返回true。

public boolean hasAllCodes(String s, int k) {
    int need = 1 << k;
    boolean[] got = new boolean[need];
    int allOne = need - 1;
    int hashVal = 0;

    for (int i = 0; i < s.length(); i++) {
        // calculate hash for s.substr(i-k+1,i+1)
        hashVal = ((hashVal << 1) & allOne) | (s.charAt(i) - '0');
        
        // hash only available when i-k+1 > 0
        if (i >= k - 1 && !got[hashVal]) {
            got[hashVal] = true;
            need--;
            if (need == 0) {
                return true;
            }
        }
    }
    return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值