和树有关的题目求深度 -> 可以利用层序遍历 -> 用到层序遍历就想到使用BFS


896. 单调数列 - 水题

class Solution:
def isMonotonic(self, A) -> bool:
if sorted(A) == A or sorted(A, reverse=True) == A:
return True
return False

690. 员工的重要性 - 简单BFS

class Solution:
def getImportance(self, employees, id):
"""
:type employees: Employee
:type id: int
:rtype: int
"""
s = 0
Q = []
for i in employees:
if i.id == id:
Q.append(i)
while len(Q) != 0:
boss = Q.pop(0)
importance = boss.importance
subordinate = boss.subordinates
s += importance
for i in employees:
if i.id in subordinate:
Q.append(i)
return s # e1 = Employee(1, 5, [2, 3])
# e2 = Employee(2, 3, [])
# e3 = Employee(3, 3, [])
# Employ = [e1, e2, e3]
# print(Solution().getImportance(Employ, 1))

111. 二叉树的最小深度 - 简单BFS

"""
BFS就是对树的层序遍历,发现的第一个叶子节点一定是深度最小的
"""
class Solution:
def minDepth(self, root: TreeNode) -> int:
if root == None:
return 0
Q = [(root, 1)]
while len(Q) != 0:
node, deepth = Q.pop(0)
if node.left == None and node.right == None:
return deepth
if node.left:
Q.append((node.left, deepth+1))
if node.right:
Q.append((node.right, deepth+1))

559. N叉树的最大深度 - 和楼上找最小深度思路一样

"""
BFS结束后肯定是到了这个树的最后一层,设置一个层数标志位,不断更新标志位,则BFS退出后标志位的值就是最后一层的层数。
"""
class Solution:
def maxDepth(self, root) -> int:
if root == None:
return 0
Q = [(root, 1)]
m = 0
while len(Q) != 0:
node, deepth = Q.pop(0)
m = deepth
for i in node.children:
Q.append((i, deepth+1))
return m

993. 二叉树的堂兄弟节点

"""
BFS - 记录每个节点的深度和父节点,再去比较题目中给定的x和y的深度与父节点
"""
class Solution:
def isCousins(self, root: TreeNode, x: int, y: int) -> bool:
if root == None:
return False
# 节点,层数,父节点
Q = [(root, 1, None)]
checkOver = 0
d = []
par = []
while len(Q) != 0:
node, depth, parent = Q.pop(0)
if node == None:
break
if node.val == x or node.val == y:
checkOver += 1
d.append(depth)
if parent:
par.append(parent.val)
else:
par.append(-10000)
if checkOver == 2:
break
if node.left:
Q.append((node.left, depth+1, node))
if node.right:
Q.append((node.right, depth+1, node))
if d[0] == d[1] and par[0] != par[1]:
return True
return False

102. 二叉树的层次遍历

"""
BFS - 利用set来记录层数
"""
class Solution:
def levelOrder(self, root: TreeNode):
if root == None:
return []
Q = [(root, 1)]
deepSet = set()
deepSet.add(1)
tmp = []
result = []
while len(Q) != 0:
node, deepth = Q.pop(0)
if deepth not in deepSet:
deepSet.add(deepth)
result.append(tmp)
tmp = []
tmp.append(node.val)
if node.left:
Q.append((node.left, deepth+1))
if node.right:
Q.append((node.right, deepth+1))
result.append(tmp)
return result

103. 二叉树的锯齿形层次遍历 - 和二叉树遍历完全一致

"""
两者代码的唯一不同在于锯齿形的遍历编号从0开始的奇数行需要逆转一下
"""
class Solution:
def zigzagLevelOrder(self, root: TreeNode):
if root == None:
return []
Q = [(root, 1)]
deepSet = set()
deepSet.add(1)
tmp = []
result = []
while len(Q) != 0:
node, deepth = Q.pop(0)
if deepth not in deepSet:
deepSet.add(deepth)
result.append(tmp)
tmp = []
tmp.append(node.val)
if node.left:
Q.append((node.left, deepth+1))
if node.right:
Q.append((node.right, deepth+1))
result.append(tmp)
# 唯一的差别就在这里
for i in range(len(result)):
if i % 2 == 1:
result[i] = result[i][::-1]
return result

127. 单词接龙 - 双向BFS

"""
使用最普通BFS模板会超时(暂无解决办法),本题可以思考为一棵树,根节点就是beginWord,它的子节点就是变换一个单词后的单词,子节点的子节点就是子节点变换一个单词... 然后在那一层发现了目标节点,返回该层的层数
"""
class Solution:
def ladderLength(self, beginWord: str, endWord: str, wordList) -> int:
if beginWord == endWord:
return 0
Q = []
for i in wordList:
if self.OneDefferent(i, beginWord):
Q.append((i, 1))
s = set()
while len(Q) != 0:
word, step = Q.pop(0)
# print(word)
if word == endWord:
return step+1
if word in wordList:
wordList.remove(word)
for i in wordList:
if self.OneDefferent(i, word):
Q.append((i, step+1))
return 0 def OneDefferent(self,str1, str2):
str1 = list(str1); str2 = list(str2)
check = 0
for i in range(len(str2)):
if str1[i] != str2[i]:
check += 1
if check > 1 :
return False
if check == 1:
return True
"""
评论中提到的双向BFS(还在理解中):
当某层数量过大的时候,BFS会耗时很多。所以采用两端一起走的方式,不断比较,那一头走的少就走那一头,如果有交集最后肯定会相遇。
"""
class Solution:
def ladderLength(self, beginWord: str, endWord: str, wordList) -> int:
if endWord not in wordList:
return 0
head = {beginWord}
tail = {endWord}
wordSet = set(wordList)
wordSet.remove(endWord)
res = 0
while head and tail:
res += 1
if len(head) > len(tail):
head, tail = tail, head nextLevel = set()
for i in head:
for j in range(len(i)):
for letter in range(97, 97+26):
# 利用二十六个字母在每一个位置进行替换
newWord = i[:j] + chr(letter) + i[j+1:]
if newWord in tail:
return res + 1
if newWord not in wordSet:
continue
wordSet.remove(newWord)
nextLevel.add(newWord)
head = nextLevel
return 0
"""
BFS双向的模板:适用于从某个初始状态到某个终止状态求最短路径 head = {初始状态}
tail = {终止状态} while head and tail:
# 每次都从短的开始
if len(head) > len(tail):
head, tail = tail, head nextLeval = set()
for i in head:
# 扩展下一层
if 扩展的下一层的某个元素 in tail:
# 表示已经找到了
return head = nextLevel
# 每次的head和tail都在更新为某层的状态 """

433. 最小基因变化 - 套用上面的双向BFS模板

"""
和上面的单词结论几乎一致,都是每次给定一个初始状态、一个终止状态,改变一个字母,找到最小的变化(其实也就是找到最小路径)
"""
class Solution:
def minMutation(self, start: str, end: str, bank) -> int:
change = ["A", "C", "G", "T"]
if end not in bank or len(bank) == 0:
return -1
head = {start}
tail = {end}
bank.remove(end)
res = 0
while head and tail:
res += 1
if len(head) > len(tail):
head, tail = tail, head nextLevel = set()
# 拓展下一层
for i in head:
for j in range(len(i)):
for cha in change:
newGene = i[:j]+cha+i[j+1:]
if newGene in tail:
return res
if newGene not in bank:
continue
nextLevel.add(newGene)
# 已经走过的就不用再走了
bank.remove(newGene)
head = nextLevel
return -1

Leetcode题解 - BFS部分题目代码+思路(896、690、111、559、993、102、103、127、433)的更多相关文章

  1. Leetcode题解 - DFS部分题目代码+思路(756、1034、1110、491、721、988)

    756. 金字塔转换矩阵 """ 学到的新知识: from collections import defaultditc可以帮我们初始化字典,不至于取到某个不存在的值的时 ...

  2. Leetcode题解 - 树、DFS部分简单题目代码+思路(700、671、653、965、547、473、46)

    700. 二叉搜索树中的搜索 - 树 给定二叉搜索树(BST)的根节点和一个值. 你需要在BST中找到节点值等于给定值的节点. 返回以该节点为根的子树. 如果节点不存在,则返回 NULL. 思路: 二 ...

  3. Leetcode题解 - 贪心算法部分简单题目代码+思路(860、944、1005、1029、1046、1217、1221)

    leetcode真的是一个学习阅读理解的好地方 860. 柠檬水找零 """ 因为用户支付的只会有5.10.20 对于10元的用户必须找一个5 对于20元的用户可以找(三 ...

  4. Leetcode题解 - DFS部分简单题目代码+思路(113、114、116、117、1020、494、576、688)

    这次接触到记忆化DFS,不过还需要多加练习 113. 路径总和 II - (根到叶子结点相关信息记录) """ 思路: 本题 = 根到叶子结点的路径记录 + 根到叶子结点 ...

  5. Leetcode题解 - 树部分简单题目代码+思路(105、106、109、112、897、257、872、226、235、129)

    树的题目中递归用的比较多(但是递归是真难弄 我

  6. Leetcode题解 - 链表简单部分题目代码+思路(21、83、203、206、24、19、876)

  7. 【LeetCode题解】二叉树的遍历

    我准备开始一个新系列[LeetCode题解],用来记录刷LeetCode题,顺便复习一下数据结构与算法. 1. 二叉树 二叉树(binary tree)是一种极为普遍的数据结构,树的每一个节点最多只有 ...

  8. leetcode题解-122买卖股票的最佳时期

    题目 leetcode题解-122.买卖股票的最佳时机:https://www.yanbinghu.com/2019/03/14/30893.html 题目详情 给定一个数组,它的第 i 个元素是一支 ...

  9. [LeetCode 题解] Spiral Matrix

    前言 [LeetCode 题解]系列传送门: http://www.cnblogs.com/double-win/category/573499.html 题目链接 54. Spiral Matrix ...

随机推荐

  1. Obeject.hasOwnProperty

    对象{ }要用for-in遍历对象内的属性,通过hasOwnProperty判断属性是否是对象本身的,而不是原型上的 数组[ ]可以通过forEach来遍历

  2. 使用docker安装虚拟机并打开ssh连接

    一.需求 最近有个需求,要连接很多个linux系统进行测试软件功能,但是我这里只有几个虚拟机,所以需要使用docker来安装几十个或者上百个虚拟机来进行测试. 二.安装docker 这里就不演示怎么安 ...

  3. 4个点说清楚Java中synchronized和volatile的区别

    作者 : Hollis 回顾一下两个关键字:synchronized和volatile 1.Java语言为了解决并发编程中存在的原子性.可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如sy ...

  4. php数组去重、魔术方法、redis常用数据结构及应用场景

    一.用函数对数组进行去重的方法 1.arrau_unique函数的作用 移除数组中重复的值. 将值作为字符串进行排序,然后保留每个值第一次出现的健名,健名保留不变. 第二个参数可以选择排序方式: SO ...

  5. python学习-while

    """while 条件: 条件满足时,干的事情.如果条件一直满足,一直去重复的执行代码.直接条件不满足为止,停止循环."""# salary ...

  6. django基础之day09,手机号校验的规则和代码编写

    通过re模块实现手机号码校验的脚本--json老师 import re 通过re模块实现手机号码校验的脚本--json老师 def mobile_validate(value): mobile_re ...

  7. IIS中部署网站

    1.安装开IIS,打开IIS(Win+R -->inetmgr.exe) 2.进入IIS主界面,右键网站,选择“添加网站”. 3.在“添加网站”对话框中,添加网站名称. 4.点击应用程序池选择, ...

  8. 一起学Vue之模板语法

    概述 Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据.所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTM ...

  9. JS---DOM---事件冒泡和阻止事件冒泡,总结事件

    事件冒泡: 多个元素嵌套, 有层次关系 ,这些元素都注册了相同的事件, 如果里面的元素的事件触发了, 外面的元素的该事件自动的触发了     事件有三个阶段: 1.事件捕获阶段  :从外向内 2.事件 ...

  10. SuperMap iDesktop .NET 10i制图技巧-----如何贴图

    当我们在没有模型数据的情况下,我们只能通过造白膜来模拟三维建筑了,但是光秃秃的建筑物显然缺乏代入感,因此需要贴图来给场景润色,本文介绍如何给道路贴图和如何给白膜贴图 道路贴图: 1.打开二维道路数据 ...