leetcode刷题笔记三十七 解数独
leetcode刷题笔记三十七 解数独
源地址:37. 解数独
问题描述:
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。
代码补充:
object Solution {
def solveSudoku(board: Array[Array[Char]]): Unit = {
//构建对应行、列、宫的情况查询数组
val boolRow = Array.ofDim[Boolean](9,9)
val boolCol = Array.ofDim[Boolean](9,9)
val boolSquarl = Array.ofDim[Boolean](9,9)
//通过设置boolean型数组标记每行出现了那些数字
for(row <- 0 until 9){
for(col <- 0 until 9){
if (board(row)(col) != '.') {
boolRow(row)(board(row)(col)-'1') = true
boolCol(col)(board(row)(col)-'1') = true
boolSquarl(row/3 *3 + col/3)(board(row)(col)-'1') = true
}
}
}
//调用回溯函数
recall(board, 0, boolRow, boolCol, boolSquarl)
}
def recall(board: Array[Array[Char]], position:Int, boolRow:Array[Array[Boolean]], boolCol:Array[Array[Boolean]], boolSquarl:Array[Array[Boolean]]):Boolean = {
var index = position
// 过滤那些不需要填入的位置
while( index < 81 && (board(index/9)(index%9) != '.')) index += 1
//成功条件
if (index < 81){
val row = index/9
val col = index%9
//由于Scala中int转Char使用的ASCII码,这里使用1-9的ACSII码
//判断当前数字没有在行、列、宫出现,出现的情况进行剪枝
for(i <- 49 to 57 if((boolRow(row)(i-49) == false) && (boolCol(col)(i-49) == false) && (boolSquarl(row/3 *3 + col/3)(i-49) == false))){
//println("this i:" + i.toChar)
//进行插入
board(row)(col) = i.toChar
boolRow(row)(i-49) = true
boolCol(col)(i-49) = true
boolSquarl(row/3 *3 + col/3)(i-49) = true
//向前推进
if(recall(board, index+1, boolRow, boolCol, boolSquarl)) {
//println("boolRow: " + boolRow.mkString)
return true
}
//当前字符位置不对,重置为'.'
board(row)(col) = '.'
boolRow(row)(i-49) = false
boolCol(col)(i-49) = false
boolSquarl(row/3 *3 + col/3)(i-49) = false
}
return false
}
return true
}
}