首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

用C语言实现递归和回溯求解数独字段

数独是一种逻辑游戏,目标是在9x9的网格中填入数字1到9,使得每行、每列以及每个3x3的子网格中的数字都不重复。递归和回溯是解决数独问题的常用算法。

基础概念

  • 递归:函数调用自身的过程。
  • 回溯:在递归过程中,如果发现当前路径不可能得到解,就返回到上一步,尝试其他路径。

实现步骤

  1. 初始化:创建一个9x9的二维数组表示数独板。
  2. 检查有效性:编写函数检查在某个位置放置某个数字是否合法。
  3. 递归求解:从第一个空格开始,尝试填入1到9的数字,如果合法则递归处理下一个空格,如果不合法则回溯。

示例代码

代码语言:txt
复制
#include <stdio.h>
#include <stdbool.h>

#define N 9

bool isValid(int board[N][N], int row, int col, int num) {
    for (int x = 0; x < N; x++) {
        if (board[row][x] == num || board[x][col] == num) {
            return false;
        }
    }

    int startRow = row - row % 3, startCol = col - col % 3;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (board[i + startRow][j + startCol] == num) {
                return false;
            }
        }
    }

    return true;
}

bool solveSudoku(int board[N][N], int row, int col) {
    if (row == N - 1 && col == N) {
        return true;
    }

    if (col == N) {
        row++;
        col = 0;
    }

    if (board[row][col] > 0) {
        return solveSudoku(board, row, col + 1);
    }

    for (int num = 1; num <= N; num++) {
        if (isValid(board, row, col, num)) {
            board[row][col] = num;
            if (solveSudoku(board, row, col + 1)) {
                return true;
            }
            board[row][col] = 0;
        }
    }

    return false;
}

void printBoard(int board[N][N]) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            printf("%d ", board[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int board[N][N] = {
        {5, 3, 0, 0, 7, 0, 0, 0, 0},
        {6, 0, 0, 1, 9, 5, 0, 0, 0},
        {0, 9, 8, 0, 0, 0, 0, 6, 0},
        {8, 0, 0, 0, 6, 0, 0, 0, 3},
        {4, 0, 0, 8, 0, 3, 0, 0, 1},
        {7, 0, 0, 0, 2, 0, 0, 0, 6},
        {0, 6, 0, 0, 0, 0, 2, 8, 0},
        {0, 0, 0, 4, 1, 9, 0, 0, 5},
        {0, 0, 0, 0, 8, 0, 0, 7, 9}
    };

    if (solveSudoku(board, 0, 0)) {
        printBoard(board);
    } else {
        printf("No solution exists\n");
    }

    return 0;
}

优势

  • 简洁直观:递归和回溯算法逻辑简单,易于理解和实现。
  • 适用广泛:适用于各种需要尝试多种可能性的问题。

类型

  • 深度优先搜索(DFS):递归和回溯通常是DFS的一种实现方式。

应用场景

  • 数独求解
  • 八皇后问题
  • 图的遍历

可能遇到的问题及解决方法

  1. 栈溢出:递归深度过大可能导致栈溢出。可以通过增加栈大小或改用迭代方法解决。
  2. 效率低下:对于复杂问题,递归和回溯可能效率不高。可以考虑剪枝优化或使用其他算法如约束传播。

通过上述代码和解释,你应该能够理解并实现一个基本的数独求解器。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

  • 数独的暴力回溯解法和Python GUI版

    (数独解法概览来自《标准数独[1]》) 用电脑解最通用的还是穷举整个解空间,根据数独规则进行剪枝和回溯。效率和递归深度、需要缓存的中间过程有关,递归深度主要由挖空的个数决定。...进一步的做法是为每个挖空的格子维护一个候选数列表,用这个列表中的值进行试数,出现矛盾就回溯,很暴力但其实挺有效的。更高级一点的舞蹈链法及利用模拟退火等方法,也还是离不开试数和回溯的思路。...因此下面主要实现的是基于候选数的回溯解法。...在Leetcode上有两道数独相关的题目,第37题就是根据输入的数独(用9×9的二维数组表示)求结果。它是用'.'代表挖空,把上面的代码改一下,提交运行的效果如下: ?...本文从解数独的手动解法引入,讲到解数独常用的回溯法,并且按照思路实现回溯代码,通过这一思路去解两个LeetCode题,为了可玩性增加随机生成一个数独的代码,并把以上功能整合为一个GUI程序,用于平时的数独训练

    1.5K20

    【JavaScript 算法】回溯法:解决组合与排列问题

    回溯法是一种通过尝试所有可能的解来解决问题的算法策略。它在组合和排列问题中尤为有效,通过递归地构建解空间树并在必要时进行回退(即“回溯”),从而找到所有满足条件的解。...(选择 in 选择列表) { 做选择; backtrack(路径, 选择列表); 撤销选择; } } 二、经典问题及其 JavaScript 实现...问题描述:求给定数组的所有排列。...排列问题:求一组元素的所有排列。 子集问题:求一组元素的所有子集。 路径问题:在图或网格中寻找所有可能的路径。 数独求解:通过回溯法求解数独问题。 四、总结 回溯法是一种解决组合和排列问题的有效方法。...通过递归地构建解空间树并在必要时进行回退,回溯法能够找到所有满足条件的解。在实际开发中,回溯法广泛应用于组合、排列、子集、路径等问题的求解。希望通过本文的介绍,大家能够更好地理解和应用回溯法。

    13410

    攻克最后一关:解数独!

    攻克回溯算法最后一关 37. 解数独 力扣题目链接:https://leetcode-cn.com/problems/sudoku-solver 编写一个程序,通过填充空格来解决数独问题。...一个数独。 答案被标成红色。 提示: 给定的数独序列只包含数字 1-9 和字符 '.' 。 你可以假设给定的数独只有唯一解。 给定数独永远是 9x9 形式的。...因为这个树形结构太大了,我抽取一部分,如图所示: 37.解数独 回溯三部曲 递归函数以及参数 递归函数的返回值需要是bool类型,为什么呢?...递归单层搜索逻辑 37.解数独 在树形图中可以看出我们需要的是一个二维的递归(也就是两个for循环嵌套着递归) 一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,一行一列确定下来之后,递归遍历这个位置放...这样,解数独这么难的问题,也被我们攻克了。 恭喜一路上坚持打卡的录友们,回溯算法已经接近尾声了,接下来就是要一波总结了。

    69810

    搞懂回溯算法,我终于能做数独了

    这是一个安卓手机中的数独游戏,我使用一个叫做 Auto.js 的脚本引擎,配合回溯算法来实现自动完成填写,并且算法记录了执行次数。...在后文,我会给出该脚本的实现思路代码以及软件工具的下载,你也可以拿来装逼用。...二、代码实现 首先,我们不用管游戏的 UI,先单纯地解决回溯算法,LeetCode 第 37 题就是解数独的问题,算法函数签名如下: void solveSudoku(char[][] board);...我们已经实现了一遍算法,掌握了其原理,回溯就是从 1 开始对每个格子穷举,最后只要试出一个可行解,就会立即停止后续的递归穷举。所以暴力试出答案的次数和随机生成的棋盘关系很大,这个是说不准的。...'; } 以上思路就可以模拟出算法穷举的过程: 公众号后台回复关键词「数独」即可下载相应脚本、工具和游戏,Auto.js 是一款优秀的开源脚本引擎,可以用 JavaScript 操作安卓手机

    53520

    回溯法解数独

    继上一篇博文《回溯法解小学数字填数练习(2)》,本文再来解一个数独的的题目。其实,在小孩子的书本上能看到4阶、6阶以及9阶的数独。如:图片图片图片本文,我们以解决9阶数独为示例。...有了9阶解法思路,4阶和6阶只要调整一些逻辑即可实现。解题思路解数独是一个经典的回溯算法问题,一种解数独的思路如下:1、定义一个9x9的二维数组来表示数独棋盘,用0表示未填写的空格。...3、在每个位置尝试填写数字时,需要检查当前位置的行、列和3x3小九宫格是否已经存在相同的数字。如果不存在冲突,就可以填写数字,然后继续递归地填写下一个位置。...4、如果填写过程中出现冲突,就需要回溯到上一个位置,尝试填写其他数字,直到找到一个合适的数字或者回溯到某个位置无解。接下来,我们就根据上述方法来写一个解数独的程序。...//递归寻找结果return doSolveRec(board);}在递归方法中实现逻辑/** * 1-9数独 * * @param board 数独棋盘内容 * @return */private

    440170

    回溯算法 | 追忆那些年曾难倒我们的八皇后问题

    递归实现和栈实现操作的区别,递归对我们来说更简洁巧妙,并且用多了会发现很多问题的处理上递归的思考方式更偏向人的思考方式,而栈的话就是老老实实用计算机(数据结构特性)的思维去思考问题。...举个例子,我们知道回溯算法用来求所有数字的排列顺序。我们分析其中一个顺序。比如数列6 8 9这个序列的话,我们用来求它的排列顺序。...力扣36 有效的数独 ? 像这种题需要考虑和八皇后还是很像,改成9*9,只不过在具体处理需要考虑横、竖和3x3小方格。 当然这题比较简单,还有一题就比较麻烦了 力扣37解数独。 ?...这里的话有两点需要注意的在这里提一下: 用二维两个参数进行递归回溯判断起来谁加谁减比较麻烦,所以我们用一个参数index用它来计算横纵坐标进行转换,这样就减少二维递归的一些麻烦。...回溯更注重试探和复原,这个过程一般借助递归。 dfs深度优先搜素,一般用栈或者递归去实现,如果用递归可能会复原也可能不复原数据,所以回溯是深搜的一种。

    73430

    使用Wolfram元编程+编译 加速一类回溯算法

    比起递归,多重循环其实更容易被编译器优化,多数编程语言中,层数很多的循环再层层嵌套If,写起来麻烦,看起来实在感人,可扩展性也差,通常要避免。...从而对程序加速,有时可以接近C语言的速度。...根据上面的思路,很容易封装一个函数sudokuSolve,求解Project Euler第96题的所有50个数独,耗时约1.5s,求解一个多解数独的全解(有一百多万个解),耗时约15秒。...幻方的一般性质为:幻方每一行之和、每一列之和、两条对角线之和都相等,都等于幻和(四阶幻和为34)。 求解所有四阶幻方,用全排列搜索空间太大,对16个数全排列有16!....pdf)也是使用Matlab实现的。

    1.3K20

    递归+回溯求解数独问题

    导读:回溯是常用的算法理论之一,很多规模较大、直接分析较为复杂的问题都可以考虑用回溯求解,例如N皇后问题、骑士周游和走迷宫问题等。...本质上,回溯问题是一种优化后的暴力求解,通过及时的剪枝和启发式的寻找最优路径,可以有效加速求解过程。回溯还常常与递归搭配使用。...空白格用 '.' 表示。 来源:力扣(LeetCode)37# 解数独 ? 一个有效的数独方案 02 数独求解 数独是一个经典的可用回溯+递归求解的问题。...:对于给定状态的数独和空白方格栈,依次尝试填充数字1-9:如果存在一个可行的数字,则在此基础上递归填充下一空白;否则,回溯上一状态,寻求其他解决方案 def fillBoard(board, locs)...由于在递归求解中是直接更改的原数独数组,所以无返回值。

    98110

    学好算法,你就可以轻轻松松解数独啦

    因此,有很多经典的问题可以利用回溯法来解决: 八皇后问题 — 如何在国际象棋棋盘的 8*8 个格子里放下八个皇后,并且让他们相互不攻击到 0-1背包问题 — 给定 n 种物品和一背包。...物品 i 的重量是 wi,其价值为 pi,背包的容量为 C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 图的着色问题 解迷宫问题 解数独问题 5....通过递归回溯法解数独 递推的方式非常便于理解,但是,既然我们通过栈空间来进行问题节点的记录,我们是否可以通过函数递归天然提供给我们的栈空间来实现问题的解决呢?...当然是可以的,递归正是回溯法最常采用的方式。 6.1. 中止条件 每个空格就是数独问题的问题节点,当我们找到一个空格时,填充当前最小的可行解,然后递归到下一个问题节点。...当无法找到可行解时,返回无解,上一层递归继续寻找下一个可行解。 直到全部递归完成或最外层函数无法找到可行解,就标志着数独的解完成了获取或者这个数独无解。 6.2.

    84220

    解数独----回溯篇1

    ---- 解数独题解集合 回溯法 位运算 ---- 回溯法 这题和八皇后有点相似,不同的是八皇后每行只放一个就可以到下一行继续尝试,而这道题每行都放完没有冲突之后才能到下一行继续尝试,所以判断的逻辑稍微比八皇后多一点...按顺序填下去,如果不是空白格,就继续递归填下一个。 直到递归到最后一个格子,board 填满了,结束递归。 为什么要回溯 每填一个空白格都是尝试,选填一个数,如果没有冲突就填上去,是一种试探。...递归函数要返回一个Boolean值,定义是:基于当前的 board,给当前的格子board[i][j]填一个数,能否最后生成正确的数独。...能否最后生成正确的数独,是靠递归子调用一个个去填,当填不下去,就撤回上一个选择,尝试别的选择。 这里如何判断填入一个数后是否会冲突,可以参考leetcode 36....【解数独】回溯 + 状态压缩(使用 bitset)

    39230

    探究解数独问题

    本篇简介: 本篇文章基于leetcode的解数独问题展开讨论;通过对36有效数独的判断的基础下利用递归,结合剪枝回溯完成对本题解答。 一·解数独原题: leetcode链接:37....因此做解数独之前我们先把如何用巧方法判断数独是否有效: 下面就是leetcode的36题了: 链接:36....二·解数独的思路: 此时我们有了上面所述判断是否符合数独的基础;这道题便用到了,简单来说;再结合上我们做过的决策树系列的题的解法思路:画树->分析如何递归->确立好函数的返回值参数类型->处理好递归出口...} 但是这里如果完整的画出决策树过于麻烦,就草图一下吧: 这里个人觉得:除了上面所说的三个check数组外,其次比较注意的就是这三个返回值的位置的设计了;把握好这点,其次就是处理好的剪枝和回溯的细节问题...一般步骤:读懂题意->画出决策树->分析如何递归,怎么递归到下一层(这些条件方便些dfs函数体,以及剪枝,回溯的处理)->直接到最后一次递归的情况分析处递归出口->涉及好函数体以及需要参数,返回类型等。

    7110

    ​LeetCode刷题实战37: 解数独

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !...今天和大家聊的问题叫做 解数独,我们先来看题面: https://leetcode-cn.com/problems/valid-sudoku/ Write a program to solve a Sudoku...空白格用 '.' 表示。 ? ? 题解 回溯法解数独 让我们想象一下已经成功放置了几个数字在数独上。 但是该组合不是最优的并且不能继续放置数字了。该怎么办?回溯。...如果还是不行,再次回溯。 ? 数独首先行,列,还有 3*3 的方格内数字是 1~9 不能重复。 声明布尔数组,表明行列中某个数字是否被使用了, 被用过视为 true,没用过为 false。...如果填充失败,那么我们需要回溯。将原来尝试填充的地方改回来。 递归直到数独被填充完成。

    37020

    回溯法+约束编程-LeetCode37(数独扫雷问题、Tuple使用)

    一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 空白格用 '.' 表示。...Note: 给定的数独序列只包含数字 1-9 和字符 '.' 。 你可以假设给定的数独只有唯一解。...给定数独永远是 9x9 形式的 解题思路: 官方的解答已经很好很清晰了,希望大家可以去看一下,主要思想为约束编程和回溯!...回溯法意思是我们需要对每个未知位置进行递归求解,使用数字1-9依次进行尝试,如果在col_, row_, block_用到了该数字,则直接continue,否则我们从这个数字开始递归求解,如果不满足条件...,则回溯,并初始化相应的状态,换另外一个数字进行递归!

    95520

    ​LeetCode刷题实战37: 解数独

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !...今天和大家聊的问题叫做 解数独,我们先来看题面: https://leetcode-cn.com/problems/valid-sudoku/ Write a program to solve a Sudoku...空白格用 '.' 表示。 题解 回溯法解数独 让我们想象一下已经成功放置了几个数字在数独上。 但是该组合不是最优的并且不能继续放置数字了。该怎么办?回溯。...如果还是不行,再次回溯。 数独首先行,列,还有 3*3 的方格内数字是 1~9 不能重复。 声明布尔数组,表明行列中某个数字是否被使用了, 被用过视为 true,没用过为 false。...如果填充失败,那么我们需要回溯。将原来尝试填充的地方改回来。 递归直到数独被填充完成。

    41500

    相关题目汇总分析总结

    目前范围:Leetcode前150题 深度优先/回溯法题目 Letter Combinations of a Phone Number/电话号码的字母组合 输入手机键盘的数字,组合所有可能的字母。...Permutations/全排列 求一组不重复的数的全排列 Permutations II/全排列 II 求一组数的全排列(有重复数字),返回不重复的全排列 Generate Parentheses.../括号生成 给定n,生成n对括号,必须正常关闭所有符号 Sudoku Solver/解数独 计算数独,假设解唯一 Combination Sum/组合总和 给定一个无重复元素的数组 candidates...给定一个目标字符串和一组单词,将目标字符串进行拆分,要求拆分出的部分在那个单词组中,拆分后的单词用空格隔开,给出所有可能的拆分情况。...深度优先总结 递归与迭代 二者相互关系 从计算机角度讲,递归是迭代的特例。这个例子是两种方式计算阶乘的javascript代码实现,可以在浏览器中,按F12调出控制台,在控制台中进行实验。

    1.6K20
    领券