LeetCode 3211.生成不含相邻零的二进制字符串:二进制枚举+位运算优化

【LetMeFly】3211.生成不含相邻零的二进制字符串:二进制枚举+位运算优化

力扣题目链接:https://leetcode.cn/problems/generate-binary-strings-without-adjacent-zeros/

给你一个正整数 n

如果一个二进制字符串 x 的所有长度为 2 的子字符串中包含 至少 一个 "1",则称 x 是一个有效 字符串。

返回所有长度为 n有效 字符串,可以以任意顺序排列。

示例 1:
输入: n = 3

输出: ["010","011","101","110","111"]

解释:

长度为 3 的有效字符串有:"010""011""101""110""111"

示例 2:
输入: n = 1

输出: ["0","1"]

解释:

长度为 1 的有效字符串有:"0""1"

提示:

  • 1 <= n <= 18

解题方法:二进制枚举

不位运算优化的话其实很简单,从 0 0 0枚举到 2 n − 1 2^n-1 2n−1,看看哪个数字对应的字符串的二进制没有连续的 0 0 0即可。这样时间复杂度为 n 2 n n2^n n2n, 18 × 2 18 = 4 , 718 , 592 18\times 2^{18}=4,718,592 18×218=4,718,592,完全在合理范围内。

有没有一种办法在 O ( 1 ) O(1) O(1)的时间复杂度内判定一个数 i i i的二进制下有没有连续两个 0 0 0呢?还真有:

将 i i i二进制下低 n n n位取反( 0 0 0变 1 1 1、 1 1 1变 0 0 0), i i i二进制下没有连续两个 0 0 0等价于 X X X二进制下没有连续两个 1 1 1。

x x x二进制下没有相邻的 1 1 1等价于 x & ( x > > 1 ) = 0 x \& (x >> 1)=0 x&(x>>1)=0。

因此问题变成了"如何快速将 i i i低 n n n位取反"。也很简单, i i i异或一个 1111..1 1111..1 1111..1即可。其中 111.1 111.1 111.1一共有 n n n位,其值等于 ( 1 < < n ) − 1 (1 << n) - 1 (1<<n)−1。

  • 时间复杂度 O ( 2 n ) O(2^n) O(2n)
  • 空间复杂度 O ( 1 ) O(1) O(1),力扣返回值不计入算法空间复杂度

AC代码

C++
cpp 复制代码
class Solution {
public:
    vector<string> validStrings(int n) {
        vector<string> ans;
        int mask = (1 << n) - 1;
        for (int i = 0; i < (1 << n); i++) {
            int x = i ^ mask;  // 取反
            if (!(x & (x >> 1))) {
                ans.push_back(bitset<18>(i).to_string().substr(18 - n));
            }
        }
        return ans;
    }
};
Go
go 复制代码
package main

import "fmt"

func validStrings(n int) []string {
    ans := make([]string, 0)
    mask := (1 << n) - 1
    for i := 0; i < (1 << n); i++ {
        x := i ^ mask
        if (x & (x >> 1) == 0) {
            ans = append(ans, fmt.Sprintf("%0*b", n, i))
        }
    }
    return ans
}
Java
java 复制代码
import java.util.List;
import java.util.ArrayList;

class Solution {
    public List<String> validStrings(int n) {
        List<String> ans = new ArrayList<>();
        int mask = (1 << n) - 1;
        for (int i = 0; i < (1 << n); i++) {
            int x = i ^ mask;
            if ((x & (x >> 1)) == 0) {
                ans.add(Integer.toBinaryString((1 << n) | i).substring(1));  // 往n位"带有前导0的二进制"的前面加个1,再去掉
            }
        }
        return ans;
    }
}
Python
python 复制代码
from typing import List

class Solution:
    def validStrings(self, n: int) -> List[str]:
        ans = []
        mask = (1 << n) - 1
        for i in range(1 << n):
            x = i ^ mask
            if not x & (x >> 1):
                ans.append(f'{i:0{n}b}')
        return ans

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

Tisfy:https://letmefly.blog.csdn.net/article/details/143352841

相关推荐
XUE_DING_E5 分钟前
Educational Codeforces Round 171
算法
Patience to do15 分钟前
Android Studio项目(算法计算器)
android·算法·android studio
这题怎么做?!?31 分钟前
模板方法模式
开发语言·c++·算法
DdddJMs__1352 小时前
C语言 | Leetcode C语言题解之第517题超级洗衣机
c语言·leetcode·题解
边疆.2 小时前
C++类和对象 (中)
c语言·开发语言·c++·算法
binqian3 小时前
【K8S】kubernetes-dashboard.yaml
算法·贪心算法
Wils0nEdwards3 小时前
Leetcode 合并 K 个升序链表
算法·leetcode·链表
好看资源平台3 小时前
深入理解所有权与借用——借用与生命周期管理
开发语言·算法·rust