递归,搜索和回溯算法--介绍

本文介绍了递归的基本概念、在数据结构(如二叉树后序遍历、快速排序和归并排序)中的应用,探讨了递归的本质和理解方法,比较了深度优先遍历与宽度优先遍历,以及回溯和剪枝技巧。最后概述了相关专题的学习路径。

递归

1.什么是递归?

函数自己调用自己的情况

 c语言 + 数据结构 (二叉、快排、归并)

二叉树的后序遍历:

        从根节点开始,先进左子树,再进右子树,到左子树之后重复这个过程,返回之后进右子树重复这个过程,最后遍历根节点。

快速排序:

        找到基准元素之后先向左边排序,再向右边排序,进入左边之后重复这个过程,返回之后进右边重复这个过程,最终整合。

归并排序:

        将一个待排序段分成两份,左边进行归并,右边进行归并,最终整体归并。

2.为什么会用到递归?

本质:

主问题 -> 相同的子问题
 子问题 -> 相同的子问题 

..................................

3.如何理解递归?(分成三个层次)

1.递归展开的细节图
2.二叉树中的题目
3.宏观看待递归的过程
        1.不要在意递归的细节展开图                                                                                                               2.把递归的函数当成一个黑盒 
        3.相信这个黑盒一定能完成这个任务  

//伪代码,二叉树后序遍历
void dfs(TreeNode* root)
{
//细节-出口
if(root == nullptr) 
    return;
else
    {

        dfs(root->left);
        dfs(root->right);
        printf(root->val);
    }
}
//伪代码,归并
void merge(nums, int left, int right)
{
//细节-出口
    if(left >= right) 
        return;
    int mid = (left + right) / 2;
    merge(nums, left, mid);
    merge(nums, mid + 1 right);
    //合并两个有序数组
}

4.如何写好一个递归?

1.先找到相同的子问题!!! -> 函数头的设计

2.只关心某一个子问题是如何解决的 -> 函数体的书写 

3.注意一下递归函数的出口即可

搜索 vs 深度优先遍历 vs 深度优先搜索 vs 宽度优先遍历 vs 宽度优先搜索 vs 暴搜

 1.对比

深度优先遍历 vs 深度优先搜索(DFS)
宽度优先遍历 vs 宽度优先搜索(BFS)

                                                        =====》本质上是一致的

遍历是形式,目的是搜索

 2.关系图

暴力枚举一遍所有的情况


搜索(暴搜)=DFS+BFS
  

3.拓展搜索问题
 

全排列问题(树状图结构问题都可以) 

三、回溯与剪枝 

回溯本质就是深搜,就是深搜过程中做了错误的决定,调回到分支处(红色线就相当于回溯)

剪枝就是回到多分支处发现原本其中一条路走过了,不再走了,相当于把它去掉了

四、整合以及规划


专题一:递归
专题二:二叉树中的深搜
专题三: 穷举vs暴搜vs深搜vs回湖vs剪枝
专题四:综合练习
专题五: FloodFill 算法
专题六:记忆化搜索 

<think>嗯,用户想了解数独求解算法递归回溯的实现方式。首先,我需要回忆一下递归回溯的基本概念。递归就是函数自己调用自己,而回溯则是一种通过试错来寻找解决方案的方法,当发现当前路径无法得到解时,就回退一步,尝试其他可能。 接下来,数独的规则是每行、每列每个3x3的小宫格内必须填入1-9且不重复。所以,算法需要填充空格,同时满足这三个条件。那递归回溯如何应用在这里呢?应该是逐个填充空格,尝试填入可能的数字,如果后续发现冲突,就回溯到上一个位置重新选择数字。 根据之前的引用资料,比如引用[4]提到回溯是一种优化后的暴力求解,通过剪枝加速。所以,在数独中,递归函数可能从第一个空格开始,尝试填入1-9中的一个数字,检查是否合法,如果合法就递归处理下一个空格。如果下一个空格无法填入任何数字,说明当前路径错误,回溯到上一个位置,尝试下一个可能的数字。 具体步骤可能是这样的:遍历数独的每个单元格,找到空格,尝试填入可能的数字,验证行、列、宫格是否冲突。如果没有冲突,递归处理下一个空格。如果所有数字都尝试过都不行,就回溯,恢复当前空格为未填状态,回到上一个位置继续尝试。 需要处理的关键点包括如何高效地找到空格,如何验证填入数字的合法性,以及递归终止条件。终止条件应该是所有空格都填满,这时就可以输出解了。 另外,引用[2]提到递归回溯对数独很有效,可能因为数独的结构适合这种逐步试探的方法。而引用[3]的C语言实现也是用递归,说明这种方法的通用性。 可能需要注意的优化点,比如优先填充可能性少的空格,减少递归次数,但用户的问题是基本实现,所以可能不需要深入优化部分,先讲清楚基础实现。 所以,整个流程应该是:找到空格→尝试数字→验证→递归回溯。代码结构大致是递归函数,参数是当前数独状态,每次调用处理下一个空格,直到填满或无法继续时回溯。 然后,代码示例部分需要展示这个逻辑,比如用Python的话,可能有一个solve_sudoku函数,里面循环1-9,检查valid,然后递归调用,如果返回True则继续,否则重置单元格。 还需要考虑如何表示数独,可能用二维数组。验证函数需要检查行、列宫格。宫格的检查可以通过确定起始行列来计算。 总结起来,回答的结构应该是先讲算法思想,再分步骤解释,然后给出代码示例,最后相关问题。需要确保使用正确的中文术语,LaTeX公式正确,如行内用$...$,独立公式用$$...$$,但数独算法可能涉及较多代码逻辑,数学公式可能较少,但如果有提到数学概念,比如组合可能,需要正确使用。</think>### 数独求解算法中的递归回溯实现方式 #### 一、算法思想 数独求解的递归回溯算法通过**逐步填充空格**并验证合法性,遇到矛盾时回退(回溯)到上一步重新选择数字,直到所有空格被正确填充[^4]。核心步骤包括: 1. **寻找空格**:遍历数独网格,找到第一个未填充的单元格。 2. **尝试填入数字**:在空格中尝试填入$1$至$9$,满足**行、列、3×3宫格**无重复。 3. **递归回溯**:若当前数字合法,递归处理下一个空格;若后续步骤无解,则回溯到当前空格并尝试其他数字。 #### 二、实现步骤 1. **合法性检查** 验证数字是否满足数独规则: - **行检查**:当前行是否已存在该数字。 - **列检查**:当前列是否已存在该数字。 - **宫格检查**:所在3×3宫格是否已存在该数字。 ```python def is_valid(board, row, col, num): # 检查行 if num in board[row]: return False # 检查列 for i in range(9): if board[i][col] == num: return False # 检查3×3宫格 start_row, start_col = 3 * (row // 3), 3 * (col // 3) for i in range(3): for j in range(3): if board[start_row + i][start_col + j] == num: return False return True ``` 2. **递归回溯函数** 递归填充空格,若遇到矛盾则回溯: ```python def solve_sudoku(board): for i in range(9): for j in range(9): if board[i][j] == 0: # 找到空格 for num in range(1, 10): if is_valid(board, i, j, num): board[i][j] = num if solve_sudoku(board): # 递归处理下一个空格 return True board[i][j] = 0 # 回溯 return False # 所有数字均不合法,触发回溯 return True # 所有空格已填满 ``` 3. **终止条件** 当遍历完所有单元格且无空格时,返回成功(数独已解)。 #### 三、复杂度与优化 - **时间复杂度**:最坏情况下为$O(9^{n})$($n$为空格数量),但实际通过剪枝(合法性检查)大幅减少尝试次数[^2]。 - **优化策略**:优先填充**候选数最少**的空格(启发式搜索),减少递归深度[^4]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值