回溯算法-深度优先搜索
来源于leetcode一道中等难度的题,匹配括号。
回溯法-深度优先搜索
回溯法思路的简单描述是:把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。
回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。
回溯法的基本行为是搜索,搜索过程使用剪枝函数来为了避免无效的搜索。
剪枝函数包括两类:1. 使用约束函数,剪去不满足约束条件的路径;
2.使用限界函数,剪去不能得到最优解的路径。
(在搜索过程中剪掉已经出现不符合条件的路径,避免继续向下展开)
问题的关键在于如何定义问题的解空间,转化成树(即解空间树)。解空间树分为两种:子集树和排列树。两种在算法结构和思路上大体相同。
当问题是要求满足某种性质(约束条件)的所有解或最优解时,往往使用回溯法。
LeetCode题解代码
public List generateParenthesis(int n) {
List list = new ArrayList<>();
if (n == 0){
return list;
}
dfs("",n,n,list);
return list;
}
public void dfs(String res ,int left,int right,List temp){
//判断是否已经达到了叶子结点,也就是最终解
if (left == 0 && right == 0){
temp.add(res);
return;
}
//剪枝
//当遍历过程中发现已经有了不符合条件的情况产生,剪去这条路径,减少不必要的搜索过程
if (right < left){
return;
}
//树的两个节点,也就是两个不同的路径,向下遍历
//采用递归的形式,将两种情况分解为树的两个节点,向下遍历
//这里递归进去之后,会在这个结点为根的情况下再次产生两个结点,直到遍历到最后的叶子结点
if (left > 0){
dfs(res + "(",left - 1,right,temp);
}
if (right > 0){
dfs(res + ")",left,right - 1,temp);
}
}