算法与数据结构 之 搜索算法

搜素算法

搜索分为广度优先搜索、深度优先搜索、A*算法。

一、广度优先算法(BFS)

1.1、基本实现和特性
BFS是从一个顶点 V。开始,沿着图的宽度遍历图中的结点,如果所有结点均被访问或找到要查找的元素,则算法终止。一般用队列数据结构来辅助实现BFS算法,采用地毯式层层推进策略。

1.2、复杂度分析
时间复杂度O(E),空间复杂度是O(V)。

1.3、步骤
广度优先搜索使用队列来实现:
1、顶点V。放到队列的末尾
2、每次从队列的头部取出一个元素,查看这个元素的相邻结点,把它们放到队列的末尾,并把这个元素记为它的下一级元素的前驱
3、找到所要找的元素时结束程序
4、如果遍历这个图还没有找到,结束程序

1.4、应用
1、Dijkstra单源最短路径算法
2、Prim最小生成树算法

二、深度优先搜索(DFS)

2.1、基本实现和特性
深度优先搜索算法的思想是从一个订单V。开始,沿着一条路一直走到底,如果发现不到目标解,那就返回到上一个结点,然后从另一条路开始走到底。这种尽量往深处走的概念即是深度优先,利用的是回溯算法思想。

2.2、复杂度分析
时间复杂度O(E),空间复杂度是O(V)

2.3、步骤
深度优先遍历图的方法是,从图中某顶点V。出发:
1、访问顶点V。
2、依次从V。的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和V。有路径相通的顶点都被访问
3、若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

2.4、应用
树或者图的搜素

三、A*算法

3.1、基本概念
A*(A-star)算法是一种静态路网中求解最短路径最有效的直接搜素方法,也是解决许多搜素问题的有效算法,算法中的距离估算值与实际值越接近,最终搜素速度越快。

四、常见面试题

例题1:200. 岛屿数量https://leetcode-cn.com/problems/number-of-islands/

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出:1
示例 2:

输入:grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3

思路:

深度优先搜索,每次搜索完,将 1 重置为 0, 1 周边(上下左右)都搜索完一圈之后,计数 + 1.
时间复杂度:O(m*n), m为二维岛屿的长度,n为岛屿的宽度
空间复杂度:O(1)

代码实现:

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        if not grid:
            return 0
        def dfs(grid, i, j):
            if not 0 <= i < len(grid) or not 0 <= j < len(grid[0]) or not grid[i][j] == '1':
                return
            grid[i][j] = '0'
            dfs(grid, i-1, j)
            dfs(grid, i, j-1)
            dfs(grid, i+1, j)
            dfs(grid, i, j+1)
        count = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '1':
                    count += 1
                    dfs(grid, i, j)
        return count

例题2:547. 朋友圈https://leetcode-cn.com/problems/friend-circles/

班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。

给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。

示例 1:

输入:
[[1,1,0],
[1,1,0],
[0,0,1]]
输出:2
解释:已知学生 0 和学生 1 互为朋友,他们在一个朋友圈。
第2个学生自己在一个朋友圈。所以返回 2 。
示例 2:

输入:
[[1,1,0],
[1,1,1],
[0,1,1]]
输出:1
解释:已知学生 0 和学生 1 互为朋友,学生 1 和学生 2 互为朋友,所以学生 0 和学生 2 也是朋友,所以他们三个在一个朋友圈,返回 1 。

思路:
深度优先搜索,dfs , 用set集合记录访问过的元素,访问完后从1标记为0,dfs搜索完一圈之后计数+1

时间复杂度:O(n^2)
空间复杂度:O(n) ,借助set集合记录访问过的元素

代码实现:

class Solution:
    def findCircleNum(self, M: List[List[int]]) -> int:
        visited = set()
        count = 0
        def dfs(i):
            for j in range(len(M)):
                if j not in visited and M[i][j] == 1:
                    visited.add(j)
                    dfs(j)
               #     M[i][j] = 0   # 这句代码没起作用,后来我基本都删除这句代码了。
        for i in range(len(M)):
            if i not in visited:
                dfs(i)
                count += 1
        return count    

2021-01-09 更新记录:该题目更新啦,题号还不变,换了一个题目,解法完全一样。废话不多说,看更新后的题目。

题目:547. 省份数量 https://leetcode-cn.com/problems/number-of-provinces/

有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

示例 1:

输入:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
输出:2
示例 2:

输入:isConnected = [[1,0,0],[0,1,0],[0,0,1]]
输出:3

思路我就不重复了,还是之前一样,直接给出参考代码,代码也还一样,换一个变量名。留一个记录,见证面试题目的换汤不换药哈~

时隔1个月还是想重复写一下思路:
题意理解:[[1,1,0],[1,1,0],[0,0,1]] 中有三个城市下标记为0,1,2. [1,1,0]表示第0个城市和第0个城市有连接,记为1, 第0个城市和第1个城市有连接,即为1,第0个城市和第2个城市没有连接,记为0,所以为 [1,1,0],其他依次类推。
[[1,1,0],
[1,1,0],
[0,0,1]]
如果把数组写成矩阵对齐的方式,很容易一眼看出1的相连有2个方阵,左上角和右下角的单独的一个1。

单独的一个城市也算一个省份,i,j在visited中都表示自身城市和其他城市的坐标位置,ij和ji只需要访问一次,ij和ji都访问会造成统计的重复。

dfs(j) 的作用就是去重,ij和ji的关系是一样,所以只能记录一次,在dfs(i)的外面进行一次计数。

class Solution:
    def findCircleNum(self, isConnected: List[List[int]]) -> int:
        visited = set()
        count = 0
        def dfs(i):
            for j in range(len(isConnected)):
                if j not in visited and isConnected[i][j] == 1:
                    visited.add(j)
                   # isConnected[i][j] = 0
                    dfs(j)
        for i in range(len(isConnected)):
            if i not in visited:
                visited.add(i)
                count += 1
                dfs(i)
        return count

撰写记录
2020.12.23-06:28:00-第一次撰写
2020.12.25-07:08:00-第二次撰写
2021.01.09-09:11:10-第三次撰写
2021.02.09-09:05:00-第四次撰写
2021.02.09-22:20:00-第五次撰写

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,783评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,396评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,834评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,036评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,035评论 5 362
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,242评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,727评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,376评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,415评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,463评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,140评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,734评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,809评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,028评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,521评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,119评论 2 341

推荐阅读更多精彩内容