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

相关推荐
MicroTech20255 分钟前
微算法科技(NASDAQ: MLGO)使用量子傅里叶变换(QFT),增强图像压缩和滤波效率
科技·算法·量子计算
㓗冽10 分钟前
矩阵问题(二维数组)-基础题70th + 发牌(二维数组)-基础题71th + 数字金字塔(二维数组)-基础题72th
c++·算法·矩阵
芜湖xin20 分钟前
【题解-Acwing】796. 子矩阵的和
算法·前缀和
shehuiyuelaiyuehao21 分钟前
23七大排序算法
数据结构·算法·排序算法
Σίσυφος190023 分钟前
E=[T]×R 的证明
算法
TracyCoder12325 分钟前
LeetCode Hot100(49/100)——33. 搜索旋转排序数组
算法·leetcode
熬了夜的程序员33 分钟前
【LeetCode】116. 填充每个节点的下一个右侧节点指针
算法·leetcode·职场和发展
郝学胜-神的一滴33 分钟前
贝叶斯之美:从公式到朴素贝叶斯算法的实践之旅
人工智能·python·算法·机器学习·scikit-learn
静心观复33 分钟前
贝叶斯公式拆解
算法
智者很聪明35 分钟前
排序算法—冒泡排序
算法·排序算法