【数据结构和算法】_09_广度 / 深度 优先搜索


 


 

【一】 Breadth - First Search(广度优先搜索)

 

比较符合人类的思维的,常用的,搜索算法,必须掌握

 

  • 示意图(

 

  • 代码(不仅适用于树,也适用于图)
# python 广度优先搜索

def BFS(graph, start, end):

	# 队列,先进先出
	queue = []
	queue.append([start])
	# visited 里的数据表示被访问过了 (对二叉树来说没必要)
	visited.add(start)

	# 当队列不为空时
	while queue:
		# 将队列头元素取出
		node = queue.pop()
		# 放进被访问过的列表里
		visited.add(node)

		# 处理后继结点
		process(node)
		nodes = generate_related_nodes(node)
		queue.push(nodes)
		
	# other processing work
	...

 


 

【二】 Depth - First Search(深度优先搜索)

 

很多时候,我们在搜索一棵树的时候,站在计算机的角度,递归会默认用 stack (栈) 的数据结构来实现,而 BFS (广度优先搜索) 则是用的 queue (队列) ,DFS (深度优先搜索) 会更符合计算机的思维

 

  • 示意图(
     

 

  • 示意图(
     

 

  • 代码(递归写法,推荐)
# python 深度优先搜索

visited = set()
def dfs(None, visited):
	visited.add(node)
	# process current node here.
	...
	for next_node in node.children():
		if not next_node in visited:
			# 递归
			dfs(next_node, visited)

 

  • 代码(非递归写法)
# python 深度优先搜索

def DFS(self, tree):
	if tree.root is None:
		return []
	
	visited, stack = [], [tree.root]

	while stack:
		node = stack.pop()
		visited.add(node)

		process(node)
		nodes = generate_related_nodes(node)
		stack.push(nodes)
	
	# other processing work
	...

 


 

【三】 Interview(面试题)

 

【3.1】 LeetCode 102:Binary Tree Level Order(二叉树的层次遍历)

Input: [ 3, 9, 20, null, null, 15, 7 ]
Output: [ [ 3 ], [ 9, 20 ], [ 15, 7 ] ]

  • BFS(广度优先搜索)
# python BFS 广度优先搜索

class Solution(object):
	def levelOrder(self, root):
		if not root: return []

		result  = []
		queue = collections.deque()
		queue.append(root)

		# visited = set(root) # 对图而言的

		while queue:
			level_size = len(queue)
			current_level = []

			for _ in range(level_size):
				node = queue.popleft()
				current_level.append(node.val)
				if node.left: queue.append(node.left)
				if node.right: queue.append(node.right)
				
			result.append(current_level)
		return result
  • DFS(深度优先搜索)
# python DFS 深度优先搜索

class Solution(object):
	def levelOrder(self, root):
		if not root: return []
		self.result  = []
		self._dfs(root, 0)
		return self.result
	
	def _dfs(self, node, level):
		if not node: return

		if len(self.result) < level + 1:
			self.result.append([])
		
		self.result[level].append(node.val)
		
		# 递归实现
		self._dfs(node.left, level + 1)
		self._dfs(node.right, level + 1)

 

【3.2】 LeetCode 104:Max depth(二叉树的最大深度)

Input: [ 3, 9, 20, null, null, 15, 7, null, 4 ]
Output: 最大深度 4

  • BFS(广度优先搜索)
# python BFS 广度优先搜索 判断叶子节点

  • DFS(深度优先搜索)
# python DFS 深度优先搜索 判断叶子节点

class Solution:
	def maxDepth(self, root):
		if not root: return 0
		# 递归,先左后右
		return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))

 

【3.3】 LeetCode 111:Min depth(二叉树的最小深度)

Input: [ 3, 9, 20, null, null, 15, 7, null, 4 ]
Output: 最小深度 2

  • BFS(广度优先搜索)
# python BFS 广度优先搜索 判断叶子节点

  • DFS(深度优先搜索)
# python DFS 深度优先搜索 判断叶子节点

class Solution:
	def minDepth(self, root):
		if not root: return 0
		# 左子树深度
		if not root.left: return 1 + self.minDepth(root.right)
		# 右子树深度
		if not root.right: return 1 + self.minDepth(root.left)

		# divide and conquer (分而治之)
		leftMinDepth = self.minDepth(root.left)
		rightMinDepth = self.minDepth(root.right)
	
		# 看最小值
		result = 1 + min(leftMinDepth, rightMinDepth) 

 

【3.4】 LeetCode 22:Generate Parentheses(括号生成)

题目说明:给出 n 代表生成括号的对数,列出所有的有效括号的组合
Input: n = 3
Output: [ ‘((()))’, ‘(()())’, ‘(())()’, ‘()(())’, ‘()()()’]

  • BFS(深度优先搜索)
# python BFS 广度优先搜索 长度为2n 递归

class Solution(object):
	def generateParenthesis(self, n):
		self.list = []
		self._gen(0, 0, n "")
		return self.list

	# 递归函数
	def _gen(self, left, right, n, result):
		'''
		left:左括号用了多少个了
		right:右括号用了多少个了
		'''
		# 若全用完了
		if left == n and right == n:
			self.list.append(result)
			return
		# 若没用完
		if left < n:
			self._gen(left+1, right, n, result+'(')
		if right < n and left > right:
			self._gen(left, right+1, n, result+')')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值