LeetCode 1980 Find Unique Binary String 全解:回溯、Cantor 对角线、随机化与 Trie 五种思路及多语言实现

发布时间:2026/11/5 18:29:22

LeetCode 1980 Find Unique Binary String 全解:回溯、Cantor 对角线、随机化与 Trie 五种思路及多语言实现 LeetCode 1980 Find Unique Binary String 全解回溯、Cantor 对角线、随机化与 Trie 五种思路及多语言实现【免费下载链接】leetcodeLeetcode solutions项目地址: https://gitcode.com/GitHub_Trending/leetcode1/leetcode本文以 articles/find-unique-binary-string.md 为骨架系统讲解 LeetCode 1980「Find Unique Binary String」这道经典题的五种解法递归回溯、迭代回溯、Cantor 对角线构造、随机化与 Trie 前缀树。读者学完将掌握「在 2^n 个二进制串中高效找出缺失串」的证明思路与编码技巧并可在 Python、Java、C、Kotlin 等仓库多语言实现中直接对照验证。前置知识动手解题前建议先具备以下基础能力Hash Set利用集合的 O(1) 查找判断某个字符串是否已存在回溯 / 递归逐字符构造解空间并探索所有可能性二进制串处理整数与二进制字符串之间的互相转换、补零操作Cantor 对角线论证可选一种数学证明技术能保证构造出「与集合中每个元素都不同」的新元素是本体的最优解的理论根基。问题本质为什么缺失串一定存在给定一个长度为n的二进制字符串数组nums共n个串每个串长度也是n要求返回任意一个不在nums中出现过的长度为n的二进制串。关键洞察在于鸽巢原理长度为n的二进制串一共有2^n种而输入只有n个因此当n ≥ 1时必然2^n n缺失串一定存在。这一事实是所有解法尤其是随机化的正确性的前提。解法一回溯递归思路既然缺失串必然存在我们只需按字典序或任意顺序系统地构造候选串逐一检查是否出现在集合中。递归回溯从「全 0」串出发逐位尝试0与1第一个不在集合中的完整串即为答案。算法步骤将nums全部存入哈希集合获得 O(1) 查询从全0字符串开始递归在第i位若i n判断当前串是否在集合中不在则返回先保持第i位为0递归若失败将第i位改为1再递归返回第一个不在集合中的串。Python 实现class Solution: def findDifferentBinaryString(self, nums: List[str]) - str: strSet {s for s in nums} def backtrack(i, cur): if i len(nums): res .join(cur) return None if res in strSet else res res backtrack(i 1, cur) if res: return res cur[i] 1 return backtrack(i 1, cur) return backtrack(0, [0 for _ in nums])仓库源码对照仓库中 python/1980-find-unique-binary-string.py 与该实现完全一致且在每次失败分支后都显式检查并返回逻辑等价。其他语言版本同样遵循「先试 0 再试 1」的骨架java/1980-find-unique-binary-string.java 使用Set.of(nums)构建不可变集合并用StringBuffer递归kotlin/1980-find-unique-binary-string.kt 用CharArray与内联递归函数backtrack返回Boolean标志cpp/1980-find-unique-binary-string.cpp 则直接对0、1两个字符做 for 循环回溯push/pop并在成员变量result非空时提前剪枝返回。注意该 C 实现的时间复杂度注释为 O(2^N · N)遍历全部候选并拼接文档正文给出的递归版本因为「先试 0、失败才试 1」的贪心顺序实际只需访问少量节点均摊为 O(n²)。复杂度时间复杂度O(n²)空间复杂度O(n)递归栈 当前串解法二回溯迭代思路递归本质上是在隐式地遍历一棵二叉树。如果只想快速拿到一个答案可以直接遍历 0 到 n 的整数将其转换为定长二进制串后检查是否在集合中。因为只检查 n1 个候选而输入只有 n 个串必然能命中一个缺失串。算法步骤将nums存入哈希集合num从0遍历到n将num转成二进制串并用前导零补齐到长度n若不在集合中直接返回兜底返回空串理论上前 n1 个候选内必能找到。Python 实现class Solution: def findDifferentBinaryString(self, nums: List[str]) - str: strSet set(nums) n len(nums) for num in range(1 n): res bin(num)[2:].zfill(n) if res not in strSet: return res return 关键细节前导零补位各语言的补位手法各不相同这是本题最容易踩坑的地方Pythonbin(num)[2:].zfill(n)JavaString.format(% n s, Integer.toBinaryString(num)).replace( , 0)C自定义toBinaryString(int num, int length)逐位检查num (1 i)JavaScriptnum.toString(2).padStart(n, 0)Gofmt.Sprintf(%0*b, n, num)Rustformat!({:0width$b}, num, width n)。复杂度时间复杂度O(n²)空间复杂度O(n)解法三Cantor 对角线论证最优思路Cantor 对角线论证是本题最优雅、最快的解法时间复杂度 O(n)且完全不需要哈希集合。核心思想对每个输入串nums[i]取其第i个字符并翻转。构造出的串在第 0 位与nums[0]不同、在第 1 位与nums[1]不同……以此类推从而保证与每一个输入串至少在一位上不同。直觉上可以想象一个 n×n 的「字符串矩阵」我们沿着对角线取字符并全部取反得到的行必然与矩阵中的每一行都不同——这正是 Cantor 用来证明实数不可数的经典手法在本题的落地。算法步骤初始化空结果串对i从0到n-1读取对角线字符nums[i][i]追加其相反字符0变11变0返回结果串。Python 实现class Solution: def findDifferentBinaryString(self, nums: List[str]) - str: res [] for i in range(len(nums)): if nums[i][i] 0: res.append(1) else: res.append(0) return .join(res)验证示例以nums [01, 10]为例nums[0][0] 0→ 追加1nums[1][1] 0→ 追加1。结果11与01在第 0 位不同、与10在第 1 位不同确实不在输入中。复杂度时间复杂度O(n)空间复杂度O(1) 额外空间结果串本身 O(n)这是面试中最推荐的答案既无集合开销也无递归深度还附带一个漂亮的数学故事。解法四随机化思路利用「候选空间远大于输入规模」这一事实2^n个可能串中只有n个被占用随机生成一个串命中缺失串的概率至少为(2^n - n) / 2^n当n稍大时该概率趋近于 1。因此反复随机生成并查集合期望尝试次数非常小。算法步骤将nums存入哈希集合无限循环每位随机取0或1拼成长度为n的串若不在集合中则返回由于输入稀疏期望尝试次数极少。Python 实现class Solution: def findDifferentBinaryString(self, nums: List[str]) - str: strSet set(nums) n len(nums) while True: res .join(random.choice(01) for _ in range(n)) if res not in strSet: return res各语言随机源示例Java 用random.nextBoolean()、C 用rand() % 2、Go 用rand.Intn(2)、Rust 用rng.gen_bool(0.5)、Swift 用Bool.random()。复杂度时间复杂度最坏情况 O(∞)理论上有无限循环可能实际期望极快空间复杂度O(n)适用提示随机化解法代码最简但属于「概率性正确」面试讲解时应主动指出其期望复杂度与最坏情况体现严谨性。解法五Trie 前缀树思路用 Trie 存储所有输入串后从根节点出发寻找「断枝」若某节点缺少0或1子节点说明存在一条不经过任何已存串的路径沿该路径走下去并用任意字符补齐即可得到一个缺失串。算法步骤将所有输入串插入 Trie从根节点遍历若0子节点缺失追加0并返回剩余位置任意填充若1子节点缺失追加1并返回若两个子节点都存在优先走1继续深入若结果长度不足n用1补齐返回构造出的串。Python 实现class Node: def __init__(self): self.children [None, None] def contains_bit(self, bit: int) - bool: return self.children[bit] is not None def put(self, bit: int): self.children[bit] Node() def get(self, bit: int): return self.children[bit] class Trie: def __init__(self): self.root Node() def insert(self, s: str): curr self.root for c in s: bit int(c) if not curr.contains_bit(bit): curr.put(bit) curr curr.get(bit) def search(self, res: str, curr) - bool: while curr.contains_bit(0) or curr.contains_bit(1): if not curr.contains_bit(0): res.append(0) return True if not curr.contains_bit(1): res.append(1) return True res.append(1) curr curr.get(1) return False class Solution: def findDifferentBinaryString(self, nums: List[str]) - str: trie Trie() for s in nums: trie.insert(s) res [] trie.search(res, trie.root) while len(res) len(nums): res.append(1) return .join(res)原文档给出了 Node / Trie 拆分的完整多语言实现Java、C、JavaScript、C#、Go、Kotlin、Swift、Rust核心结构一致children[2]数组 containsBit / put / get三个方法Rust 版使用OptionBoxTrieNode表达可选子节点。复杂度时间复杂度O(n²)建树 O(n²)查找 O(n)空间复杂度O(n²)Trie 解法适合作为「数据结构选型」的展示当问题演化成需要多次查询或动态增删时前缀树结构能复用。常见陷阱陷阱一枚举全部 2^n 个候选虽然缺失串必然存在但直接遍历2^n个可能串是指数级开销n稍大就会超时。最优做法只需检查n1个候选解法二或直接使用 Cantor 对角线解法三。陷阱二忘记给二进制串补前导零整数转二进制后长度可能小于n例如n3时1应写成001而非1。忘记补零会导致生成的串长度错误无法与输入串正确比较。解法二的所有语言实现都显式做了补位请务必保留这一步。陷阱三误解 Cantor 对角线对角线法的精髓是翻转第 i 个串的第 i 个字符从而与每个串都在「自己那一行」不同。常见的错误是固定翻转某一位如总是翻转第一位这样只能保证与部分串不同无法覆盖全部输入。小结与仓库对照五种解法由「暴力」到「精巧」递进复杂度从 O(n²) 逐步收敛到 O(n)解法核心思路时间复杂度空间复杂度递归回溯逐位构造 集合去重O(n²)O(n)迭代回溯遍历 0..n 转定长二进制串O(n²)O(n)Cantor 对角线翻转对角线上每个字符O(n)O(1) 额外随机化概率命中缺失串期望极小O(n)Trie 前缀树沿缺失子节点构造O(n²)O(n²)本仓库围绕该题提供了可直接运行的完整实现Python、Java、C、Kotlin均以递归回溯为基线解法代码注释中标注了各自的复杂度分析适合作为刷题后的对照与复习材料。原文档 articles/find-unique-binary-string.md 还给出了其余语言JavaScript、C#、Go、Swift、Rust 等的完整 tab 实现可作为多语言横向对比的参考。【免费下载链接】leetcodeLeetcode solutions项目地址: https://gitcode.com/GitHub_Trending/leetcode1/leetcode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/25 3:49:00

VSCode + CMake 构建配置指南:从环境搭建到工程实践

1. 为什么非要在 VSCode 里配一套 CMake先回答一个很多人纠结的问题:我本来是写单片机的,或者我一直在用某款 IDE 写 C/C,为什么要折腾 VSCode 和 CMake?我自己的感受是:VSCode 本身定位就是个「编辑器」,它…

2026/11/5 18:29:21

IDEA配置Tomcat全攻略:从版本选择到部署调试的完整指南

先把话放前面:这篇是给那些在 IDEA 里折腾 Tomcat 折腾到怀疑人生的人写的。不管你是刚学 Java Web 的新手,还是从 MyEclipse 转过来的老用户,只要你在 2023 版的 IntelliJ IDEA 里想把 Tomcat 跑起来,这篇文章就是照着做完就能跑…

2026/11/4 23:43:13

VS2022启动报错“无法找到一个或多个组件”?完整排查修复指南

我自己的电脑前两天就翻车了。早上到工位,像往常一样双击 VS2022,结果没进启动页,一个弹窗先拍在我脸上——“无法找到一个或多个组件”。我第一反应是项目文件坏了?换了个几个解决方案也一样。然后我打开 Visual Studio Installe…

2026/11/5 16:51:33

EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析

1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被…

2026/11/5 16:26:13

Rust原来很简单二:所有权系统

Part 2 核心篇 —— 所有权系统 本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理 6…

2026/11/5 15:00:49

基于Hadoop+Spark的民宿智能推荐系统设计与实现

1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享…

2026/11/5 14:10:30

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配RS485,解决远距离温度监控难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑