You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化Python数独求解程序?解决RecursionError递归深度超限问题

Python数独求解程序的效率优化与递归错误解决

我编写了一个Python数独求解程序,但效率极低,尝试次数过多时会触发错误:RecursionError: maximum recursion depth exceeded while calling a Python object,仅能偶尔运行极简单的数独。作为编程新手,我想知道如何提升程序效率?

以下是我的代码:

listekords = []

bo = [[0,2,1,0,0,3,0,4,0]
     ,[0,0,0,0,1,0,3,0,0]
     ,[0,0,3,4,0,5,0,0,0]
     ,[0,0,0,1,0,0,0,3,8]
     ,[0,8,9,0,0,0,4,7,0]
     ,[0,6,0,8,7,0,2,0,0]
     ,[9,0,0,0,0,0,0,0,4]
     ,[2,0,0,0,0,0,1,0,0]
     ,[0,0,0,5,8,2,0,0,0]]

def printso():
    for i in range(len(bo)):
        if i % 3 == 0 and i != 0:
            print("----------------")

        for j in range(len(bo[0])):
            if j != 8:
                print(bo[i][j], end="")
            else:
                print(bo[i][j])

            if (j+1)% 3 == 0 and j != 8:
                print("|", end="")

def passt(number, ky, kx):
    if number in bo[ky]:
        return False
    else:
        for z in range(len(bo)):
            if bo[z][kx] == number:
                return False

        for x in range(len(bo)):
                ky1 = ky // 3
                kx1 = kx // 3
                c = x // 3

                if kx1 == 0:
                    for y in bo[x][0:3:1]:
                        if y == number and c == ky1:
                            return False

                if kx1 == 1:
                    for y in bo[x][3:6:1]:
                        if y == number and c == ky1:
                            return False

                if kx1 == 2:
                    for y in bo[x][6:9:1]:
                        if y == number and c == ky1:
                            return False

                if x == 8:
                    return True

def isempty(i, j):
    return bo[i][j] == 0

def back():
    [i, j] = listekords.pop(len(listekords)-1)
    b = bo[i][j]
    print(b)
    bo[i][j] = 0
    printso()
    return b+1

def forward(b, i, j):
    print("vor")
    bo[i][j] = b
    listekords.append([i, j])
    printso()
    return b

def solve(d, b):
    for i in range(len(bo)):
        for j in range(len(bo[0])):
            if isempty(i, j):
                while not passt(b, i, j):
                    b += 1
                    print(b)

                if b > 9:
                    b = back()
                else:
                    forward(b, i, j)
                    b = 1
                print(d)
                solve(d+1, b)

solve(1, 1)
printso()

问题分析与优化方案

1. 递归逻辑混乱导致深度溢出

你的solve函数每次递归都会从头遍历整个棋盘,遇到第一个空单元格就处理,然后再次递归,这会导致同一单元格被反复处理,递归深度远超实际需要的81层,最终触发递归深度错误。标准回溯应该找到一个空单元格,尝试所有合法数字,递归求解,失败则回溯,而不是反复从头遍历。

2. passt函数效率低下

区块检查部分逻辑冗余,遍历整个9行再判断是否属于目标区块,完全可以直接计算目标3x3区块的起始坐标,只遍历9个单元格:

  • 区块起始行:(ky // 3) * 3
  • 区块起始列:(kx // 3) * 3
  • 遍历从起始行到起始行+3,起始列到起始列+3的单元格即可

3. 全局变量与回溯逻辑复杂

用全局listekords记录坐标容易出错,且back/forward函数的打印操作会大幅拖慢速度,实际回溯只需要在递归失败时将单元格重置为0即可。


优化后的代码

bo = [[0,2,1,0,0,3,0,4,0]
     ,[0,0,0,0,1,0,3,0,0]
     ,[0,0,3,4,0,5,0,0,0]
     ,[0,0,0,1,0,0,0,3,8]
     ,[0,8,9,0,0,0,4,7,0]
     ,[0,6,0,8,7,0,2,0,0]
     ,[9,0,0,0,0,0,0,0,4]
     ,[2,0,0,0,0,0,1,0,0]
     ,[0,0,0,5,8,2,0,0,0]]

def print_board():
    for i in range(len(bo)):
        if i % 3 == 0 and i != 0:
            print("---------------------")
        for j in range(len(bo[0])):
            if j % 3 == 0 and j != 0:
                print("| ", end="")
            print(f"{bo[i][j]} ", end="")
        print()

def is_valid(number, row, col):
    # 检查行
    if number in bo[row]:
        return False
    # 检查列
    for r in range(9):
        if bo[r][col] == number:
            return False
    # 检查3x3区块
    block_row_start = (row // 3) * 3
    block_col_start = (col // 3) * 3
    for r in range(block_row_start, block_row_start + 3):
        for c in range(block_col_start, block_col_start + 3):
            if bo[r][c] == number:
                return False
    return True

def solve_sudoku():
    # 找到第一个空单元格
    for row in range(9):
        for col in range(9):
            if bo[row][col] == 0:
                # 尝试1-9的数字
                for num in range(1, 10):
                    if is_valid(num, row, col):
                        bo[row][col] = num
                        # 递归求解,如果成功直接返回True
                        if solve_sudoku():
                            return True
                        # 递归失败,回溯
                        bo[row][col] = 0
                # 所有数字都尝试过,无解,返回False
                return False
    # 所有单元格填满,求解成功
    return True

if solve_sudoku():
    print("求解完成:")
    print_board()
else:
    print("该数独无解")

优化点说明

  • 递归逻辑简化:每次找到第一个空单元格,尝试所有合法数字,递归成功则立即返回,避免无效递归
  • is_valid函数优化:区块检查直接定位目标3x3区域,减少遍历次数
  • 去掉全局状态依赖:回溯逻辑直接在递归中处理,无需额外记录坐标的全局列表
  • 移除冗余打印:仅在求解完成后打印结果,大幅提升运行速度

内容的提问来源于stack exchange,提问作者hansi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:32:33