Leetcode-Sudoku Solver(数独)

本文介绍了一种基于深度优先搜索的数独求解算法。通过维护候选数字集合并采用特定策略减少搜索范围来提高效率。文章详细解释了算法流程及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题的解题思路如下:

(1):list,
(2):list,dfs
(3),,,block
(4),

这道题的编程细节如下:

(1):,,,,,,,,

(2):,使copy,,bug,使,

…一些可能的优化:

(1):利用一个判定函数判断当集合元素大于1个的时候,应该优先选择能够筛选掉最多元素的那一个。但是由于数据量比较小,所以这个优化不一定在这种输入下占优势
代码如下:进行一次排序
def get_priority(ele):
                return count[ele]

            if len(candidates)>1:
                count = Counter((chain(*copy_row,*copy_col,*copy_block)))
                copy_candidates.sort(key = get_priority,reverse = True)
            else:
                copy_candidates = candidates.copy()

(2):可以维护一个堆,只有当更新的时候某一个元素的值小于当前堆的最小值时,我们才重建堆。否则就直接从堆里面取最小值(堆顶元素)。同样由于leetcode数据量很小,这个优化不见得能加快。

class Solution(object):
    def solveSudoku(self, board):
        def gen_pos():
            for i in range(n):
                for j in range(n):
                    yield i,j
        def block_id(i,j):
            return i//3*3+j//3
        def delete(container,d):
            for item in container:
                item.discard(d)

        def recover(container,initial):
            for item_c,item_ini in zip(container,initial):
                item_c.clear()
                item_c.update(item_ini)

        def update():
            if len(cells)==0:return True
            (candidates,index) = min(((c,index) for index,c in cells.items()),key = lambda x:len(x[0]))
            copy_candidates = candidates.copy()
            if len(candidates)==0:return False

            row,col = index//9,index%9
            block = row//3*3+col//3
            copy_row = [cells[r].copy() for r in range(row*9,row*9+9) if r in cells]
            copy_col = [cells[c].copy() for c in range(col,81,9) if c in cells]
            copy_block = [cells[b].copy() for b in block_indexs[block] if b in cells]

            for selected in copy_candidates:

                delete((cells[r] for r in range(row*9,row*9+9) if r in cells),selected)
                delete((cells[c] for c in range(col,81,9) if c in cells),selected)
                delete((cells[b] for b in block_indexs[block] if b in cells),selected)
                result_board[index//9][index%9] = selected
                cells.pop(index)

                if not update():
                    cells[index] = copy_candidates.copy()####fuck
                    recover((cells[r] for r in range(row*9,row*9+9) if r in cells),copy_row)
                    recover((cells[c] for c in range(col,81,9) if c in cells),copy_col)
                    recover((cells[b] for b in block_indexs[block] if b in cells),copy_block)
                else:
                    return True
            return False

        n = len(board)
        all_num = {str(i+1) for i in range(n)}
        rows = [all_num-set(row) for row in board]
        cols = [all_num-set(col) for col in zip(*(row for row in board))]
        blocks,block_indexs = [set() for i in range(n)],[[]for j in range(n)]
        cells = [ [] for i in range(n*n) ]
        result_board = [[s for s in row] for row in board]

        for i,j in gen_pos():
            index = block_id(i,j)
            blocks[index].add(board[i][j])
            block_indexs[index].append(i*9+j)
        blocks = {index:all_num-item_set for index,item_set in enumerate(blocks) }
        cells = {i*9+j:(rows[i]&cols[j]&blocks[block_id(i,j)]) \
        for i,j in gen_pos() if board[i][j]=='.'}


        update()
        for i,(v1,v2) in enumerate(zip(board,result_board)):
            board[i] = ''.join(v2)

最后结果:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值