37. 解数独

Posted lgz0921

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了37. 解数独相关的知识,希望对你有一定的参考价值。

题目链接:https://leetcode-cn.com/problems/sudoku-solver/

吐槽:自己好久没写递归了,导致这个题让我的周末很不愉快~~,都他喵快写了3个小时~~,也与自己对kotlin不熟悉有关~~

思路:就是递归~~先说明一下坑点(借助代码里的内容说明):

1. flag,题目明确说明只有一个结果。有结果就结束递归!!!!之前打ACM的时候都是有结果就输出,现在知道,其实程序输出结果后还在继续运行,如果不停止,就会导致最后内存中的board不是自己想要的结果~~~

2.题目中的colValue和rowValue是自己加上的,因为kotlin的语法特性导致传的值都是val类型不能修改,但是不能写成Solution的成员变量,这样会导致,多次递归沿用的是同一个colValue和rowValue的值

3.注意如果之前已经填过值,记得接着递归下去,否则递归停止,也不是自己想要的结果。这个坑点跟我的个人写法有关系~~~

主要思路就是:signRow标记行有哪儿个数字被用过了([行][数]),signCol标记列有哪儿个数字被用过了([列][数]),signCell标记小的正方形有哪儿个数字被用过了([小正方形][数]),小正方形的表示方法: /3  的意思是小正方形的表示就是 3*3 的一共有9个小正方形~~~。标记讲完了。接下来就是搜索,就是按行填,每填出一个符合条件的,就接着往下搜。当一行结束,跳到下一行,直到搜完。最后flag标记一下搜完,搜完就是所有的填的数字都满足条件了。然后判断一下,告诉程序不用后面的搜索了,直接return~~~

上代码:

class Solution {

    private val signRow = Array(9) { BooleanArray(9) }
    private val signCol = Array(9) { BooleanArray(9) }
    private val signCell = Array(3) { Array(3) { BooleanArray(9) } }
    private var flag = false

    private fun sign(board: Array<CharArray>) {
        for (i in 0 until 9) {
            for (j in 0 until 9) {
                if (board[i][j] != '.') {
                    signRow[i][(board[i][j] - '0') - 1] = true
                    signCol[j][(board[i][j] - '0') - 1] = true
                    signCell[i / 3][j / 3][(board[i][j] - '0') - 1] = true
                }
            }
        }
    }

    private fun dfs(board: Array<CharArray>, row: Int, col: Int) {
        var colValue = col
        var rowValue = row
        if (colValue == 9) {
            colValue = 0
            rowValue++
        }
        if (rowValue == 9) {
            flag = !flag
            return
        }
        if (board[rowValue][colValue] != '.') {
            dfs(board, rowValue, colValue + 1)
        }
        for (value in 1..9) {
            if (board[rowValue][colValue] == '.' && !signRow[rowValue][value - 1] && !signCol[colValue][value - 1] && !signCell[rowValue / 3][colValue / 3][value - 1]) {
                board[rowValue][colValue] = (value + '0'.toInt()).toChar()
                signRow[rowValue][value - 1] = true
                signCol[colValue][value - 1] = true
                signCell[rowValue / 3][colValue / 3][value - 1] = true
                dfs(board, rowValue, colValue + 1)
                if (flag) return
                board[rowValue][colValue] = '.'
                signRow[rowValue][value - 1] = false
                signCol[colValue][value - 1] = false
                signCell[rowValue / 3][colValue / 3][value - 1] = false
            }
        }

    }

    fun solveSudoku(board: Array<CharArray>): Unit {
        sign(board)
        dfs(board, 0, 0)
    }
}

以上是关于37. 解数独的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 37.解数独

算法leetcode|37. 解数独(rust重拳出击)

37. 解数独

LeetCode-37.解数独

leetcode——37.解数独

Backtracking_37. 解数独