DFS和BFS
特别的DFS,pony.ai一面出的题目:给定两个正整数a, b (<= 10^18)。可以置换a数中每个数位的位置,求能够得到的比b小的最大的数。不允许前导0
注意这里递归和回溯的次数,时间复杂度是O(n)
DFS
DFS是一种枚举所有完整路径来遍历所有情况的搜索方法。最佳实现方法:递归。当然也可以自建栈代替递归,但是往往较麻烦,递归相当于调用系统栈,本质一样。
其中一类DFS问题的解法:给定一个序列,枚举这个序列所有的子序列(可以不连续)。
例1:01背包问题的DFS解法
对于每一个物品,DFS有两个分支,遍历所有的分支。当选择物品的综合超过背包容量,说明该路径走入了死胡同,则需要回到最近的一个岔道口。核心代码如下。
注意到每件物品都有两种选择,故时间复杂度是O(2^n),优化的点有,在sumW+W[index]小于V时再进入迭代
void DFS(int index,int sumW,int sumC){
if(index==n){已经完成物品选择的处理}
DFS(index+1,SumW,sumC);//不选第index件物品
DFS(index+1,SumW+W[index],sumC+C[index]);//选第index件物品
}例2:N个整数中选择K个数的和等于X的所有方案,冲突的话选择其平方和最大的一个。用向量记录添加进方案当中的元素,进入DFS下一步的时候将元素入栈。
void DFS(int index,int nowK,int sum,int sumSqu){
if(nowk==k&&sum==x){
if(sumSqu>maxsumSqu){
maxsumSqu=sumSqu;
ans=tmp;
}
return;
}
if(index==n||nowk>k||sum>x)return;
//在DFS递归前和递归后分别设置状态和取消状态,是回溯的典型特征。
//选择index元素
tmp.push_back(A[index]);
DFS(index+1,nowk+1,sum+A[index],sumSqu+A[index]*A[index]);
tmp.pop_back();
//不选index
DFS(index+1,nowk,sum,sumSqu);
}DFS应用之全排列
阿哈算法:将问题形象化为降1-n编号的扑克牌放入n个盒子中,用book[]数组记录该数字已经放过。
DFS和BFS配合vis数组,都可以用来求解连通域的个数
DFS回溯法解n皇后
邓书改进迭代版本,原版见cppSTL。
递归版本
BFS
相比DFS用递归系统栈实现,BFS用自建队列实现。
BFS的模板
用BFS求m*n矩阵中连通域的个数。(注意,这里可以用x[4],y[4]枚举四个方向)
迷宫中求S到T的最少步数,用BFS,并且记录节点深度(S深度为0,然后每一层深度是上一层+1)
队中元素时是结构体的注意事项,如果直接在队列汇中存储结构体,那么,对队列中的副本的修改不会影响原元素。这就是说,如果需要对队列中的元素进行修改,最好在队列中存储元素的编号而非元素本身,如果数组的话则是下标。
BFS求二叉树的层次遍历
BFS求二叉树的最小深度
BFS判断是否是满二叉树,将空节点也入队,如果出队的是空节点,而此时已经出队了n个元素,则是满二叉树
m*n图中的最短路径问题,都可以用BFS来最方便实现
Last updated
Was this helpful?