Description

給定一個字串陣列 nums,包含 n 個長度為 n 的互不相同的二進位字串。回傳一個長度為 n 且不在 nums 中的二進位字串(保證至少存在一個答案)。

Example:

Input: nums = [“01”,“10”] Output: “11”

Intuition#

核心思路:用 Cantor 對角線法,第 i 位取 nums[i] 第 i 位的反,保證結果與每個字串至少一位不同。

  • n 個長度為 n 的字串,共有 2^n 種可能,必定有至少一個不在其中
  • Cantor 對角線法:構造字串 result[i] = flip(nums[i][i])
  • 這保證 result 與 nums[i] 至少在第 i 位不同,所以 result 不等於任何 nums[i]

Approaches#

1: 回溯 / 暴力搜索#

  • 概念: 用 HashSet 存所有 nums,嘗試構造每個可能的二進位字串直到找到不在集合中的
  • 時間複雜度: O(2^n * n) 最差情況
  • 空間複雜度: O(n^2)
class Solution {
    fun findDifferentBinaryString(nums: Array<String>): String {
        val set = nums.toHashSet()
        val n = nums[0].length

        fun backtrack(current: StringBuilder): String? {
            if (current.length == n) {
                val s = current.toString()
                return if (s !in set) s else null
            }

            for (bit in charArrayOf('0', '1')) {
                current.append(bit)
                val result = backtrack(current)
                if (result != null) return result
                current.deleteCharAt(current.lastIndex)
            }

            return null
        }

        return backtrack(StringBuilder())!!
    }
}

⭐2: Cantor 對角線法#

  • 概念: 第 i 位取 nums[i][i] 的反,保證構造出的字串與每個 nums[i] 都不同
  • 時間複雜度: O(n)
  • 空間複雜度: O(n)
class Solution {
    fun findDifferentBinaryString(nums: Array<String>): String {
        val sb = StringBuilder()
        for (i in nums.indices) {
            sb.append(if (nums[i][i] == '0') '1' else '0')
        }
        return sb.toString()
    }
}

🔑 Takeaways#

  • Pattern: 構造不在集合中的元素 → Cantor 對角線法
  • 關鍵技巧: 對角線法的核心保證——result[i] != nums[i][i],所以 result 與任何 nums[i] 至少有一位不同;這是一個數學 / 構造性的 O(n) 解法,比回溯優雅得多