|
| 1 | +/** |
| 2 | + * [37] 解数独 |
| 3 | + * |
| 4 | + * 编写一个程序,通过填充空格来解决数独问题。 |
| 5 | + * 数独的解法需 遵循如下规则: |
| 6 | + * <ol> |
| 7 | + * 数字 1-9 在每一行只能出现一次。 |
| 8 | + * 数字 1-9 在每一列只能出现一次。 |
| 9 | + * 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图) |
| 10 | + * </ol> |
| 11 | + * 数独部分空格内已填入了数字,空白格用 '.' 表示。 |
| 12 | + * |
| 13 | + * <div class="top-view__1vxA"> |
| 14 | + * <div class="original__bRMd"> |
| 15 | + * <div> |
| 16 | + * 示例 1: |
| 17 | + * <img src="https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2021/04/12/250px-sudoku-by-l2g-20050714svg.png" style="height:250px; width:250px" /> |
| 18 | + * 输入:board = [["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]] |
| 19 | + * 输出:[["5","3","4","6","7","8","9","1","2"],["6","7","2","1","9","5","3","4","8"],["1","9","8","3","4","2","5","6","7"],["8","5","9","7","6","1","4","2","3"],["4","2","6","8","5","3","7","9","1"],["7","1","3","9","2","4","8","5","6"],["9","6","1","5","3","7","2","8","4"],["2","8","7","4","1","9","6","3","5"],["3","4","5","2","8","6","1","7","9"]] |
| 20 | + * 解释:输入的数独如上图所示,唯一有效的解决方案如下所示: |
| 21 | + * <img src=" https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2021/04/12/250px-sudoku-by-l2g-20050714_solutionsvg.png" style="height:250px; width:250px" /> |
| 22 | + * |
| 23 | + * |
| 24 | + * 提示: |
| 25 | + * |
| 26 | + * board.length == 9 |
| 27 | + * board[i].length == 9 |
| 28 | + * board[i][j] 是一位数字或者 '.' |
| 29 | + * 题目数据 保证 输入数独仅有一个解 |
| 30 | + * </div> |
| 31 | + * </div> |
| 32 | + * </div> |
| 33 | + * |
| 34 | + */ |
| 35 | +pub struct Solution {} |
| 36 | + |
| 37 | +// problem: https://leetcode.cn/problems/sudoku-solver/ |
| 38 | +// discuss: https://leetcode.cn/problems/sudoku-solver/discuss/?currentPage=1&orderBy=most_votes&query= |
| 39 | + |
| 40 | +// submission codes start here |
| 41 | + |
| 42 | +use std::collections::HashSet; |
| 43 | + |
| 44 | +impl Solution { |
| 45 | + fn init_sets(board: &mut Vec<Vec<char>>) -> (Vec<HashSet<char>>, Vec<HashSet<char>>, Vec<HashSet<char>>) { |
| 46 | + let (mut rows, mut cols, mut blks) = (vec![], vec![], vec![]); |
| 47 | + for j in 0..9 { |
| 48 | + let mut row = HashSet::new(); |
| 49 | + let mut col = HashSet::new(); |
| 50 | + let mut blk = HashSet::new(); |
| 51 | + rows.push(row); |
| 52 | + cols.push(col); |
| 53 | + blks.push(blk); |
| 54 | + } |
| 55 | + for i in 0..81 { |
| 56 | + let (m, n) = (i/9, i%9); |
| 57 | + let blk_idx = m / 3 * 3 + n / 3; |
| 58 | + match board[m][n] { |
| 59 | + '.' => {}, |
| 60 | + c => { |
| 61 | + cols[n].insert(c); |
| 62 | + rows[m].insert(c); |
| 63 | + blks[blk_idx].insert(c); |
| 64 | + }, |
| 65 | + } |
| 66 | + } |
| 67 | + return (rows, cols, blks); |
| 68 | + } |
| 69 | + |
| 70 | + pub fn solve_sudoku(board: &mut Vec<Vec<char>>) { |
| 71 | + let (mut rows, mut cols, mut blks) = Self::init_sets(board); |
| 72 | + let mut stack = vec![]; |
| 73 | + let mut i = 0; |
| 74 | + let mut sc = '1'; |
| 75 | + |
| 76 | + 'outer: while i < 81 { |
| 77 | + let (m, n) = (i/9, i%9); |
| 78 | + let blk_idx = m / 3 * 3 + n / 3; |
| 79 | + match board[m][n] { |
| 80 | + '.' => { |
| 81 | + let mut found = false; |
| 82 | + for c in sc..='9' { |
| 83 | + if rows[m].contains(&c) || cols[n].contains(&c) || blks[blk_idx].contains(&c) { |
| 84 | + continue; |
| 85 | + } |
| 86 | + board[m][n] = c; |
| 87 | + |
| 88 | + rows[m].insert(c); |
| 89 | + cols[n].insert(c); |
| 90 | + blks[blk_idx].insert(c); |
| 91 | + |
| 92 | + stack.push((i, c)); |
| 93 | + found = true; |
| 94 | + break; |
| 95 | + } |
| 96 | + if !found { |
| 97 | + (i, sc) = stack.pop().unwrap(); |
| 98 | + let (m, n) = (i/9, i%9); |
| 99 | + let blk_idx = m / 3 * 3 + n / 3; |
| 100 | + board[m][n] = '.'; |
| 101 | + rows[m].remove(&sc); |
| 102 | + cols[n].remove(&sc); |
| 103 | + blks[blk_idx].remove(&sc); |
| 104 | + sc = (sc as u8 + 1) as char; |
| 105 | + continue 'outer; |
| 106 | + } |
| 107 | + }, |
| 108 | + _ => {}, |
| 109 | + } |
| 110 | + sc = '1'; |
| 111 | + i += 1; |
| 112 | + } |
| 113 | + } |
| 114 | +} |
| 115 | + |
| 116 | +// submission codes end |
| 117 | + |
| 118 | +#[cfg(test)] |
| 119 | +mod tests { |
| 120 | + use super::*; |
| 121 | + |
| 122 | + #[test] |
| 123 | + fn test_37() { |
| 124 | + let mut board = vec![ |
| 125 | + vec!['5','3','.','.','7','.','.','.','.'], |
| 126 | + vec!['6','.','.','1','9','5','.','.','.'], |
| 127 | + vec!['.','9','8','.','.','.','.','6','.'], |
| 128 | + vec!['8','.','.','.','6','.','.','.','3'], |
| 129 | + vec!['4','.','.','8','.','3','.','.','1'], |
| 130 | + vec!['7','.','.','.','2','.','.','.','6'], |
| 131 | + vec!['.','6','.','.','.','.','2','8','.'], |
| 132 | + vec!['.','.','.','4','1','9','.','.','5'], |
| 133 | + vec!['.','.','.','.','8','.','.','7','9'], |
| 134 | + ]; |
| 135 | + Solution::solve_sudoku(&mut board); |
| 136 | + assert_eq!(board, vec![ |
| 137 | + vec!['5','3','4','6','7','8','9','1','2'], |
| 138 | + vec!['6','7','2','1','9','5','3','4','8'], |
| 139 | + vec!['1','9','8','3','4','2','5','6','7'], |
| 140 | + vec!['8','5','9','7','6','1','4','2','3'], |
| 141 | + vec!['4','2','6','8','5','3','7','9','1'], |
| 142 | + vec!['7','1','3','9','2','4','8','5','6'], |
| 143 | + vec!['9','6','1','5','3','7','2','8','4'], |
| 144 | + vec!['2','8','7','4','1','9','6','3','5'], |
| 145 | + vec!['3','4','5','2','8','6','1','7','9'], |
| 146 | + ]); |
| 147 | + } |
| 148 | +} |
0 commit comments