題目描述: 給定一個 9×9 的數獨棋盤,判斷目前的填法是否合法。合法規則如下:
空格以 '.' 表示,不需填滿棋盤,只需驗證已填數字是否符合規則。
解題思路: 最直覺的作法是使用三組雜湊集合(hash sets)來同時追蹤三種限制條件:
掃描整個棋盤的每個格子 (r, c):
'.',直接跳過。box_id = (r / 3) * 3 + (c / 3),這樣 9 個子方格分別映射到 0–8。rows[r]、cols[c]、boxes[box_id]。false。true。由於棋盤固定為 9×9 = 81 個格子,所有操作都是常數時間與空間,因此整體複雜度為 O(1)。
時間複雜度:O(1) — 棋盤固定為 9×9 = 81 個格子,無論輸入內容如何,迴圈總迭代次數恆為 81 次,每次操作均為 O(1),整體為常數時間。
空間複雜度:O(1) — 使用了 27 個雜湊集合(9 列 + 9 行 + 9 方格),每個集合最多存 9 個元素(1–9),總空間需求為固定常數,與輸入規模無關。
1. Initialize 3 arrays of hash sets: rows[9], cols[9], boxes[9]. 2. For each cell (r, c) in the 9x9 board: a. If board[r][c] == '.', skip. b. Compute box_id = (r / 3) * 3 + (c / 3). c. If val exists in rows[r] OR cols[c] OR boxes[box_id], return false. d. Insert val into rows[r], cols[c], and boxes[box_id]. 3. Return true.
位元遮罩法 O(1):使用整數的位元(bit mask)代替雜湊集合。由於數字範圍為 1–9,可用一個 9 位元的整數表示已出現過的數字(第 k 位代表數字 k 是否出現)。位元運算(AND、OR)效率更高,且記憶體使用更緊湊,但可讀性稍低。
陣列代替雜湊集合 O(1):使用 int rows[9][9]、cols[9][9]、boxes[9][9] 的二維陣列,rows[r][digit-1] 記錄列 r 的數字 digit 是否出現。陣列存取比雜湊集合更快(無雜湊碰撞),且記憶體配置是連續的,對快取更友好,實務上比雜湊集合更常用。