LeetCode---搜索算法

搜索算法

图Graph的概念

图是一种由节点和边构成的数据结构,实际上树也是一种特殊的图。图可以用来表示现实世界中的很多事物:道路交通系统、航班线路、互联网连接等等。

顶点Vertex (节点Nond):是图的基本组成部分,顶点具有名称标识key,也可以携带数据项payload。
边Edge(弧Arc):作为两个顶点之间关系的表示,边连接两个顶点;边可以是无向或有向的,相应的图称为“无向图”和“有向图”。
权重Weight:为了表达从一个顶点到另一个顶点的代价,可以给边赋权;例如公交网中的两个站点之间的“距离”、“通行时间”和“票价”都可以作为权重。

在这里插入图片描述
路径Path:图中的路径,是由边依次连接起来的顶点序列;无权路径的长度为边的数量;带权路径的长度为所有边权重的和;如下图的一条路径(V3,V4,V0,V1),其边为{(V3,V4,7),(V4,V0,1),(V0,V1,5)}。
在这里插入图片描述
圈Cycle:圈是首尾顶点相同的路径,如下图中(V5,V2,V3,V5V)是一个圈。如果有向图中不存在任何圈,则称为“有向无圈图”(directed acylic graph:DAG)。
在这里插入图片描述

图的抽象数据类型

在这里插入图片描述
在这里插入图片描述

邻接矩阵

优点:简单。
缺点:空间复杂度太高。
在这里插入图片描述
在这里插入图片描述

邻接列表

在这里插入图片描述
在这里插入图片描述

class Node(object):
    def __init__(self, key):
        self.key = key
        self.connected_to = {
   }

    # 添加一个边
    def add_nbr(self, nbr, weight=0):
        self.connected_to[nbr] = weight

    # 获取当前节点所有连接
    def get_connections(self):
        return self.connected_to.keys()

    # 获取当前节点的key
    def get_key(self):
        return self.key

    # 获取指定边的权重
    def get_weight(self, nbr):
        return self.connected_to[nbr]

    # 打印当前节点连接的所有节点信息
    def __str__(self):
        return str(self.key) + ' connected to: ' + str([x.key for x in self.connected_to])


class Graph(object):
    def __init__(self):
        self.nodes = {
   }
        self.node_num = 0

    # 添加节点
    def add_node(self, key):
        self.node_num += 1
        new_node = Node(key)
        self.nodes[key] = new_node
        return new_node

    # 通过key获取节点
    def get_node(self, key):
        return self.nodes.get(key)

    # 添加一条边
    def add_edge(self, from_node, to_node, weight=0):
        if from_node not in self.nodes:
            self.add_node(from_node)
        if to_node not in self.nodes:
            self.add_node(to_node)
        self.nodes[from_node].add_nbr(self.nodes[to_node], weight)

    # 获取图中所有节点
    def get_nodes(self):
        return self.nodes.keys()

    def __iter__(self):
        return iter(self.nodes.values())

    # in操作符
    def __contains__(self, key):
        return key in self.nodes

图的搜索算法
广度优先BFS

给定图G,已经开始搜索的起始顶点S。BFS搜索所有从S可到达其他顶点的边,并且在到达更远的距离k+1的顶点之前,BFS会找到全部距离为k的顶点。

# 标准的广度优先的基本流程
def bfs():
	定义队列;
	
    定义备忘录,用于记录已经访问的位置;
    
    判断边界条件,是否能直接返回结果的;

    将起始位置加入到队列中,同时更新备忘录;

    while 队列不为空:
        获取当前队列中的元素个数。
        for (元素个数):
            取出一个位置节点。
            判断是否到达终点位置。
            获取它对应的下一个所有的节点。
            for (每个节点)
	            条件判断,过滤掉不符合条件的位置。
	            新位置重新加入队列。
深度优先DFS

深度优先于广度优先算法流程基本一致,只是将队列改为了栈存储检查的节点。

# 标准的广度优先的基本流程
def bfs():
	定义栈;
	
    定义备忘录,用于记录已经访问的位置;
    
    判断边界条件,是否能直接返回结果的;

    将起始位置加入到栈中,同时更新备忘录;

    while 栈不为空:
        获取当前栈中的元素个数。
        for (元素个数):
            取出一个位置节点。
            判断是否到达终点位置。
            获取它对应的下一个所有的节点。
            for (每个节点)
	            条件判断,过滤掉不符合条件的位置。
	            新位置重新加入栈。

LeetCode

BFS

1091. 二进制矩阵中的最短路径

题目链接

解法:广度优先搜索
def shortestPathBinaryMatrix(grid):
    # 边界情况
    if len(grid) == 0 or len(grid[0]) == 0 \
            or grid[0][0] == 1 or grid[-1][-1] == 1:
        return -1

    if len(grid) == 1:
        return 1

    row = len(grid)
    cow = len(grid[0])

    queue = [(0, 0)]
    ans = 0

    while len(queue) > 0:
        node_num = len(queue)
        for i in range(node_num):
            node = queue.pop(0)

            # 到达右下角节点时返回结果
            if node == [cow-1, row-1]:
                return ans + 1

            # 八个方向偏移量:左上、左、左下、下、右下、右、右上、上
            offsets = [[-1, -1], [-1, 0], [-1, 1], [0, 1],
                       [1, 1], [1, 0], [1, -1], [0, -1]]

            # 判断八个方向的节点是否满足要求
            for offset in offsets:
                x = node[0] + offset[0]
                y = node[1] + offset[1]
				
				# 越界
                if not 0 <= x <= cow-1:
                    continue
				# 越界
                if not 0 <= y <= row-1:
                    continue
				# 非零值
                if grid[x][y] != 0:
                    continue

                # 满足要求时加入队列,并且把当前节点置为1
                queue.append([x, y])
                grid[x][y] = 1
     
        # 遍历一次结束后,步数+1
        ans += 1

    return -1

如下图,因为广度优先

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值