二分查找、DFS、BFS、记忆化搜索的区别

二分查找(中分查找),顾名思义,是一种查找算法,每次取数据中的中间值,时间复杂度通常为O(log2(n).

20210313090428873

深度优先搜索(DFS)顾名思义是一种搜索算法,每次“不撞南墙不回头”。一般用栈或递归来实现,时间复杂度通常为O(2^n)或O(n^2)

20200506000711954

广度优先搜索(BFS),也被称为宽度优先搜索,也是一种搜索算法,每次有“分身”来进行查找,就像网络的传播,所以时间复杂度会比 深度优先搜索(DFS)略快一点

20200506000711822

f7b43abe-4bae-4476-baea-a5309673896f

记忆化搜索是一种通过记录已经遍历过的状态的信息,从而避免对同一状态重复遍历的搜索实现方式。

那它们有什么不同呢?

当问题的答案具有某种单调性时,我们就可以二分答案。 单调性可以理解为,随着x的增加,对应y值逐渐增大——单调递增;或者随着x的减小,对应y值逐渐减小——单调递减。

深度优先搜索(DFS)与 广度优先搜索(BFS)其实都是一种暴力程序,时间复杂度都较高。

记忆化搜索确保了每个状态只访问一次,它也是一种常见的动态规划(dp)实现方式。你可以理解为:

记忆化搜索=搜索的形式+动态规划(dp)的思想


二分查找模板:

int l=1,r=n+1,mid;
while(l<r)
{
    mid=(l+r)>>1;//或者 mid=l+(r-l)>>1;
    if(a[mid]>=x) r=mid;
    else l=mid+1;   
}
cout<<l;

深度优先搜索(DFS)模板:

void DFS(type n){//当前搜索的是第几个节点
	if(符合条件) cout<<答案;return;//递归的出口
	for(//选择该阶段的可以访问的所有节点){  
		标记已访问该点;
		DFS(n+1);             //进入下一阶段,往下递归
		还原访问现场;
	}
}

广度优先搜索(BFS)模板:

void bfs(起始状态){
    queue<int> qu;//创建队列
    qu.push(起始状态入队);
    //起始状态标记
    while(!qu.empty()){//当队列非空
	//获取从起始状态可以到达的下一个点
        if(这个点可以走)
            qu.push(当前状态);//该状态入队
        …………………
        处理(队首)qu.top();
        相应操作;
        qu.pop();//队首弹出队
    }//一次循环结束,执行下一次循环
}

记忆化搜索模板:

int dfs()
{
    if(有解) return 解;
    for(枚举路径总数)
        if(满足条件)
        {
            if(到达目的)return 值;
            else 
            {
                int t=dfs(继续递归);
                找出最优值;
            }
        }
    储存最优值;
    return 最优值;
}

综上所述,如果问题是一个单调性的序列的话,那么使用优先级是:

二分查找 > 记忆化搜索 > 广度优先搜索(BFS)> 深度优先搜索(DFS)

但如果问题无单调性,那么二分查找将无法使用

记忆化搜索也不适用于求连通块等题目

所以同学们要根据题目选择适当的搜索算法!

你们喜欢哪种搜索算法?
  • 二分查找
  • 深度优先搜索(DFS)
  • 广度优先搜索(BFS)
  • 记忆化搜索
0 投票人
1 个赞