|
| 1 | +34.有效的数独 |
| 2 | +=== |
| 3 | + |
| 4 | + |
| 5 | +### 题目 |
| 6 | + |
| 7 | +请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。 |
| 8 | + |
| 9 | +数字 1-9 在每一行只能出现一次。 |
| 10 | +数字 1-9 在每一列只能出现一次。 |
| 11 | +数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图) |
| 12 | + |
| 13 | + |
| 14 | +注意: |
| 15 | + |
| 16 | +- 一个有效的数独(部分已被填充)不一定是可解的。 |
| 17 | +- 只需要根据以上规则,验证已经填入的数字是否有效即可。 |
| 18 | +- 空白格用 '.' 表示。 |
| 19 | + |
| 20 | + |
| 21 | + |
| 22 | + |
| 23 | + |
| 24 | + |
| 25 | +``` |
| 26 | +输入:board = |
| 27 | +[["5","3",".",".","7",".",".",".","."] |
| 28 | +,["6",".",".","1","9","5",".",".","."] |
| 29 | +,[".","9","8",".",".",".",".","6","."] |
| 30 | +,["8",".",".",".","6",".",".",".","3"] |
| 31 | +,["4",".",".","8",".","3",".",".","1"] |
| 32 | +,["7",".",".",".","2",".",".",".","6"] |
| 33 | +,[".","6",".",".",".",".","2","8","."] |
| 34 | +,[".",".",".","4","1","9",".",".","5"] |
| 35 | +,[".",".",".",".","8",".",".","7","9"]] |
| 36 | +``` |
| 37 | +输出:true |
| 38 | + |
| 39 | +``` |
| 40 | +输入:board = |
| 41 | +[["8","3",".",".","7",".",".",".","."] |
| 42 | +,["6",".",".","1","9","5",".",".","."] |
| 43 | +,[".","9","8",".",".",".",".","6","."] |
| 44 | +,["8",".",".",".","6",".",".",".","3"] |
| 45 | +,["4",".",".","8",".","3",".",".","1"] |
| 46 | +,["7",".",".",".","2",".",".",".","6"] |
| 47 | +,[".","6",".",".",".",".","2","8","."] |
| 48 | +,[".",".",".","4","1","9",".",".","5"] |
| 49 | +,[".",".",".",".","8",".",".","7","9"]] |
| 50 | +``` |
| 51 | +输出:false |
| 52 | +解释:除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。 |
| 53 | + |
| 54 | + |
| 55 | +提示: |
| 56 | + |
| 57 | +- board.length == 9 |
| 58 | +- board[i].length == 9 |
| 59 | +- board[i][j] 是一位数字(1-9)或者 '.' |
| 60 | + |
| 61 | + |
| 62 | +### 思路 |
| 63 | + |
| 64 | +有效的数独满足以下三个条件: |
| 65 | + |
| 66 | +- 同一个数字在每一行只能出现一次; |
| 67 | + |
| 68 | +- 同一个数字在每一列只能出现一次; |
| 69 | + |
| 70 | +- 同一个数字在每一个小九宫格只能出现一次。 |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +- i是行标 |
| 75 | +- j是列标 |
| 76 | +- 数字从char直接转换成int,会变成对应的ASCII数字码,而不是原来的数值。解决方法就是当前char数字减'0':用两个char数字的ASCII码相减,差值就是原来char数值直接对应的int数值。 |
| 77 | + - 为什么不是减'0',而是减'1'? |
| 78 | + - 若运行了大佬的代码你会发现,减'0'的话会出现`ArrayIndexOutOfBoundsException`的异常。因为后面的代码将这个`num`作为了数组的下标。本身数组设置的就是9个位置,下标范围是`[0~8]`,那么遇到数字9作为下标的时候,不就越位了吗,所以就要减1,char转换成int的同时还能解决后面越位的情况。 |
| 79 | +- boolean数组的巧妙建立 |
| 80 | + - 第一个[]存放第?行/列/块 |
| 81 | + - 第二个[]存放 相应数字 |
| 82 | + - 结合起来解释就是:第?行/列/块 是否 出现过相应数字 |
| 83 | + |
| 84 | +- 行标决定一组block的起始位置(因为block为3行,所以除3取整得到组号,又因为每组block为3个,所以需要乘3),列标再细分出是哪个block(因为block是3列,所以除3取整) |
| 85 | + |
| 86 | +``` |
| 87 | +blockIndex = i / 3 * 3 + j / 3的原因: |
| 88 | +[0, 0, 0, 1, 1, 1, 2, 2, 2] |
| 89 | +[0, 0, 0, 1, 1, 1, 2, 2, 2] |
| 90 | +[0, 0, 0, 1, 1, 1, 2, 2, 2] |
| 91 | +[3, 3, 3, 4, 4, 4, 5, 5, 5] |
| 92 | +[3, 3, 3, 4, 4, 4, 5, 5, 5] |
| 93 | +[3, 3, 3, 4, 4, 4, 5, 5, 5] |
| 94 | +[6, 6, 6, 7, 7, 7, 8, 8, 8] |
| 95 | +[6, 6, 6, 7, 7, 7, 8, 8, 8] |
| 96 | +[6, 6, 6, 7, 7, 7, 8, 8, 8] |
| 97 | +``` |
| 98 | + |
| 99 | +- blockIndex的规律探寻 |
| 100 | + - 微观`9x9` -> 宏观`3x3` |
| 101 | + - (1)`i/3`为行号,`j/3`为列号 |
| 102 | + - (2)二维数组思路:`行号*列数+列号`,即位置 |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | +```java |
| 108 | + |
| 109 | +class Solution { |
| 110 | + public boolean isValidSudoku(char[][] board) { |
| 111 | + // 记录某行,某位数字是否已经被摆放 |
| 112 | + boolean[][] row = new boolean[9][9]; |
| 113 | + // 记录某列,某位数字是否已经被摆放 |
| 114 | + boolean[][] col = new boolean[9][9]; |
| 115 | + // 记录某 3x3 宫格内,某位数字是否已经被摆放 |
| 116 | + boolean[][] block = new boolean[9][9]; |
| 117 | + |
| 118 | + for (int i = 0; i < 9; i++) { |
| 119 | + for (int j = 0; j < 9; j++) { |
| 120 | + if (board[i][j] != '.') { // 只处理数字格子 |
| 121 | + int num = board[i][j] - '1'; |
| 122 | + int blockIndex = i / 3 * 3 + j / 3; |
| 123 | + if (row[i][num] || col[j][num] || block[blockIndex][num]) { |
| 124 | + return false; |
| 125 | + } else { |
| 126 | + row[i][num] = true; |
| 127 | + col[j][num] = true; |
| 128 | + block[blockIndex][num] = true; |
| 129 | + } |
| 130 | + } |
| 131 | + } |
| 132 | + } |
| 133 | + return true; |
| 134 | + } |
| 135 | +} |
| 136 | +``` |
| 137 | + |
| 138 | +--- |
| 139 | +- 邮箱 :charon.chui@gmail.com |
| 140 | +- Good Luck! |
| 141 | + |
| 142 | + |
0 commit comments