Leetcode做题日记:37. 解数独(PYTHON)

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需遵循如下规则:

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

空白格用 ‘.’ 表示。
Note:

给定的数独序列只包含数字 1-9 和字符 '.' 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。

第一次的代码:
首先设置一个函数,判断数字i是否可以插入,然后设置递归函数,在’ . '处插入数字,当9x9表格被填满后,返回表格x

	A=['1','2','3','4','5','6','7','8','9']
        def buchongtu(x,s,sx,sy):
            for i in range(9):
                if x[sy][i]==s: #判断行
                    return False
                if x[i][sx]==s: #判断列
                    return False
            a=3*(sx//3+1)
            b=3*(sy//3+1)
            for i in range(a-3,a): #判断所属3x3表格
                for j in range(b-3,b):
                    if x[j][i]==s:
                        return False
            return True #可行返回True
        
        def jsd(X,s,sx,sy):
            x=X[:] #避免直接修改表格,选择使用切片
            x[sy][sx]=s #将s填入表格
            while x[sy][sx] in A: #当此格是数字时,不可填
                sx+=1             #遍历到不是数组的格子
                if sx==9: #遍历到行尾
                    sy=sy+1
                    sx=0
                if sy==9: #遍历完表格,返回答案
                    return x
            for i in A: #从1-9填写此空格
                if buchongtu(x,i,sx,sy): #如果数字可行
                    jsd(x,i,sx,sy) #迭代
        
        return jsd(board,board[0][0],0,0)

但是没解出来,有可能是在递归过程中,每一个数独解都是从1-9遍历,有一个解猜错误之后,会不断返回一个NONE,导致程序提前结束
第二次代码:
修改了jsd函数,却忘记修好buchongtu函数,导数我一直没有得到答案,因为在jsd函数中已经对x[sy][sx]赋值,如果不修改,buchongtu函数会一直返回False。在jsd函数中,在添加数字的同时判断是否是正确数字,因为只有一个解,在递归过程中,已经把数字全部填写好了。

	A=['1','2','3','4','5','6','7','8','9']
        def buchongtu(x,s,sx,sy):
            for i in range(9):
                if x[sy][i]==s and i!=sx: #防止选择sx列
                    return False
                if x[i][sx]==s and i!=sy: #防止选择sy行
                    return False
            a=3*(sx//3+1)
            b=3*(sy//3+1)
            for i in range(a-3,a): #判断3x3表格
                for j in range(b-3,b):
                    if x[j][i]==s and j!=sy and i!=sx:
                        return False  #防止选择[sy][sx]坑
            return True
        
        def jsd(x):
            for i in range(9):
                for j in range(9):
                    if x[i][j]=='.': #对空操作
                        for k in A:
                            x[i][j]=k #填写k
                            if buchongtu(x,k,j,i) and jsd(x):
                                return True #如果正确,返回True
                            x[i][j]='.' #如果k不正确,则先不填写,等重填
                        return False #如果没有返回True,表明没有数字可填
                                     #第一个数字就填错了,则返回False,阻止
                                     #第一个数字的填写,只有全部正确才能填
            return True #当两个for不返回值时,表明已经遍历结束,刚才填写正确       
        
        jsd(board)

908ms,排名50%
如果jsd()不采用两个for循环,可采用while:
作用是一样的遍历整个列表的空

	def jsd(x,index):
            while index <81:#有点巧妙,计算行i,列j
                i=index/9
                j=index%9
                if x[i][j]=='.':
                    for k in A:
                        x[i][j]=k
                        if buchongtu(x,k,j,i) and jsd(x,index):
                            return True
                        x[i][j]='.'
                    return False
                index+=1
            return True        
        
        jsd(board,0)

676ms,排名57%
当然也可以while结束后再for循环:

	def jsd(x,index):
            while index <81:
                i=index/9
                j=index%9
                if x[i][j]=='.':
                    break #反正都是每次递归都会填写一个数
                index+=1  #所以每次调用只需要找一个空就行了  
            
            if index<81:#如果没满
                for k in A:
                    x[i][j]=k
                    if buchongtu(x,k,j,i) and jsd(x,index+1):#这里+1可去
                        return True #确保填写的是正确的
                    x[i][j]='.'
                return False #如无法填写,返回重填
            else: #如果满了
                return True        
        
        jsd(board,0)

608ms,排名58%

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值