Medium
题目描述
给定一个字符串数组 nums,其中包含 n 个长度为 n 的唯一二进制字符串,返回一个长度为 n 且不在 nums 中出现的二进制字符串。如果有多个答案,你可以返回其中任意一个。
示例 1:
输入:nums = ["01","10"]
输出:"11"
解释:"11" 不在 nums 中出现。"00" 也是正确答案。
示例 2:
输入:nums = ["00","01"]
输出:"11"
解释:"11" 不在 nums 中出现。"10" 也是正确答案。
示例 3:
输入:nums = ["111","011","001"]
输出:"101"
解释:"101" 不在 nums 中出现。"000"、"010"、"100" 和 "110" 也是正确答案。
约束条件:
n == nums.length1 <= n <= 16nums[i].length == nnums[i]只包含 ‘0’ 或 ‘1’nums中的所有字符串都是唯一的
提示:
- 我们可以将给定的字符串转换为十进制整数
- 我们可以使用递归来生成所有可能的字符串吗?
解题思路
这道题有几种不同的解法思路:
方法一:Cantor对角化(推荐)
这是最巧妙的解法,基于Cantor对角化定理。我们构造一个新的二进制字符串,使得它在第 i 位上的值与 nums[i] 的第 i 位不同。这样构造出的字符串必然不会与数组中的任何字符串相同。
方法二:哈希表 + 枚举
将所有给定的二进制字符串存入哈希表,然后枚举所有可能的长度为 n 的二进制字符串(从 0 到 2^n-1),找到第一个不在哈希表中的字符串。
方法三:递归回溯 使用递归逐位构造二进制字符串,每次尝试添加 ‘0’ 或 ‘1’,如果当前构造的字符串可能与某个给定字符串匹配,则进行剪枝。
其中方法一最为巧妙且效率最高,时间复杂度仅为 O(n),是最推荐的解法。
代码实现
class Solution {
public:
string findDifferentBinaryString(vector<string>& nums) {
string result = "";
for (int i = 0; i < nums.size(); i++) {
// 对角化:第i位与nums[i]的第i位不同
result += (nums[i][i] == '0') ? '1' : '0';
}
return result;
}
};
class Solution:
def findDifferentBinaryString(self, nums: List[str]) -> str:
result = ""
for i in range(len(nums)):
# 对角化:第i位与nums[i]的第i位不同
result += '1' if nums[i][i] == '0' else '0'
return result
public class Solution {
public string FindDifferentBinaryString(string[] nums) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < nums.Length; i++) {
// 对角化:第i位与nums[i]的第i位不同
result.Append(nums[i][i] == '0' ? '1' : '0');
}
return result.ToString();
}
}
var findDifferentBinaryString = function(nums) {
let result = "";
for (let i = 0; i < nums.length; i++) {
// 对角化:第i位与nums[i]的第i位不同
result += nums[i][i]
复杂度分析
| 复杂度类型 | Cantor对角化 | 哈希表枚举 | 递归回溯 |
|---|---|---|---|
| 时间复杂度 | O(n) | O(n + 2^n) | O(2^n) |
| 空间复杂度 | O(1) | O(n) | O(n) |
推荐使用 Cantor对角化方法,它具有最优的时间和空间复杂度。