深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。(Wiki)
(直到走不下去才往回走)
基本模板
int search(int t)
{
if(满足输出条件)
{
输出解;
}
else
{
for(int i=1;i<=尝试方法数;i++)
if(满足进一步搜索条件)
{
为进一步搜索所需要的状态打上标记;
search(t+1);
恢复到打标记前的状态;//也就是说的{回溯一步}
}
}
}
1.全排列问题(leetcode.46):
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[[1,2,3],[1,3,2], [2,1,3], [2,3,1],[3,1,2],[3,2,1]]
思路分析:
这是一个非常典型的使用 回溯算法 解决的问题。解决回溯问题,一定不要偷懒,拿起纸和笔,画出一个树形结构,思路和代码就会比较清晰了。
方法:回溯算法(深度优先遍历+状态重置)
以示例 [1,2,3] 为例,因为是排列问题,我们只要按顺序选取数字,保证上一层选过的数字不在下一层出现,就能够得到不重不漏的所有排列方法,画出树形结构如下图:
注意:
1、在每一层,我们都有若干条分支供我们选择。由于是排列问题,之前使用过的数字,在下一层中不能再选取,那么从当前层走到下一层的时候,我们就要问一问自己,哪些数字已经使用过。在编码实现中,可以使用一个布尔型数组 used,用于记录之前(当前路径之前的层)哪些数字使用过。
2、在程序执行到上面这棵树的叶子结点的时候,此时递归到底,方法要返回了,对于这个最后一层选取的数,要做两件事情:(1)释放对它的占用;(2)将它从当前选取放进的排列中弹出。当前,在每一层的方法执行完毕,要返回的时候,都需要这么做。这两点可以简单概括为“状态重置”。
代码部分:
代码力求清晰准确,里边的每一步都可以对应基本模板填写。
package Algorithm.DFS;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class FullPermutationTest {
//从叶子节点到根节点形成的一条路径,就是题目要求的一个排列;
//在更深层可选的数一定不能包括在之前层选过的数,所以需要使用一个数组used记录哪些数在之前层选过
//DFS的核心理解是在每一个分叉位置都是一个新i了,所以每一层i是独立的,回溯的时候意味着一个分支走完了
//所以回到分叉位的时候状态要重置
public static List<List<Integer>> permute(int[] nums){
//如果nums是空,生成空list并返回
List<List<Integer>> res=new ArrayList<>();
if(nums==null||nums.length==0){
return res;
}
//used数组和len的定义
int len=nums.length;
boolean[] used=new boolean[len];
makePermution(nums,used,0,len,new Stack<>(),res);
return res;
}
public static void makePermution(int[] nums,boolean[] used,int curSize,
int len,Stack<Integer> stack,List<List<Integer>> res){
//根据格式,满足输出条件,输出解
//此时stack已保存了nums中所有数字,成为了一个完整排列
//成为完整排列,退出
if(curSize==len){
res.add(new ArrayList<>(stack));
return;
}else
{
for(int i=0;i<len;i++)
if(!used[i])
{
stack.push(nums[i]);
used[i]=true;
//往下一层进
makePermution(nums,used,curSize+1,len,stack,res);
//回溯,出栈和置标志位
stack.pop();
used[i]=false;
}
}
}
public static void main(String args[]){
int[] nums={1,2,3};
List<List<Integer>> result=permute(nums);
for (int i=0;i<result.size();i++){
System.out.println(result.get(i));
}
}
}
后续问题待更新。
参考资料:
作者:STZG 链接:https://blog.csdn.net/weixin_43272781/article/details/82959089
作者:liweiwei1419 链接:https://leetcode-cn.com/problems/two-sum/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/
来源:https://blog.csdn.net/gloria0610/article/details/96807642