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

相关推荐
Forever Nore35 分钟前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考2 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX3 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面3 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号4 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽4 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI4 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者6 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者6 小时前
【征程6】校准量化中HistogramObserver解析
算法
OuO-26 小时前
笔试强训 Day 34:ISBN 号码、kotori 和迷宫、矩阵最长递增路径
java·算法·矩阵