目录
2.队列
队列与栈类似,差别仅在于向队列里添加元素时,元素被加到尾部(入队),而提取元素时则从队列头部开始(出队)。这种机制称作FIFO(first in, first out,先进先出);而栈则被称作LIFO(last in, first out,后进先出)。
在 Python 的标准库中,有两个类实现了队列。第一是 Queue 类,这是一个同步实现,意味着多个进程可以同时访问同一个对象。它涉及并发机制,因为它在执行同步的时候使用的信号机制会拖慢执行速度。第二是 Deque 类(Double EndedQueue,即双向队列),除了提供标准方法,即在尾部使用append(element) 添加元素和在头部使用 popleft() 提取元素之外,它还提供了额外方法,用于在队列头部使用 appendleft(element) 添加元素和在尾部使用 pop() 提取元素。我们把这种队列称作双向队列。
基本应用-广度优先遍历
-树:层序遍历
-图:无权图的最短路径
树:层序遍历
102. 二叉树的层次遍历
给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
例如:
给定二叉树: [3,9,20,null,null,15,7]
,
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def _levelOrder(self, level, result, node):
if node:
if level == len(result): #说明当前level层还没有遍历
result.append([])
result[level].append(node.val)
self._levelOrder(level+1, result, node.left)
self._levelOrder(level+1, result, node.right)
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
level, result = 0, list()
self._levelOrder(level, result, root)
return result
法二:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
q, result = [root], []
while any(q):
tmp = list()
for _ in range(len(q)):
node = q.pop(0)
tmp.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
result.append(tmp)
return result
107. 二叉树的层次遍历 II
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
例如:
给定二叉树 [3,9,20,null,null,15,7]
,
3
/ \
9 20
/ \
15 7
返回其自底向上的层次遍历为:
[
[15,7],
[9,20],
[3]
]
法一:
改下102二叉树层次遍历 的返回值
return result[::-1]
法二:
# Definition for a binary tree node.
#class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrderBottom(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
q, result = [root], []
while any(q):
tmp = list()
for _ in range(len(q)):
node = q.pop(0)
tmp.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
result.insert(0, tmp)#指定位置插入
return result
103. 二叉树的锯齿形层次遍历
给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
例如:
给定二叉树 [3,9,20,null,null,15,7]
,
3
/ \
9 20
/ \
15 7
返回锯齿形层次遍历如下:
[
[3],
[20,9],
[15,7]
]
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def zigzagLevelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
q , result = [root] , []
i = 1
#any(x)判断x对象是否为空对象,如果都为空、0、false,则返回false,如果不都为空、0、false,则返回true
#all(x)如果all(x)参数x对象的所有元素不为0、''、False或者x为空对象,则返回True,否则返回False
while any(q):
tmp = list()
for _ in range(len(q)):
node = q.pop(0)
tmp.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
#上面这部分是不变的
if i%2 == 0:
tmp.reverse()
i+=1
result.append(tmp)
return result
199. 二叉树的右视图
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例:
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:
1 <---
/ \
2 3 <---
\ \
5 4 <---
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def rightSideView(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
q, tmp_res = [root] ,[]
while any(q):
tmp = list()
#遍历当前层并将值存储在tmp列表,同时将下一层添加到q中
for _ in range(len(q)):
node = q.pop(0)
tmp.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
tmp_res.append(tmp)
res = [i[-1] for i in tmp_res]
return res
图:无权图的最短路径
279. 完全平方数
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...
)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12
输出: 3
解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13
输出: 2
解释: 13 = 4 + 9.
class Solution(object):
def numSquares(self, n):
"""
:type n: int
:rtype: int
#思路1:状态转移:dp[n] = min(dp[n-i^2]) + 1,if n不是完全平方数,如果是完全平方数返回1,O(n * sqrt n),在测试用例间保留DP中间结果(通过类属性),
#思路2:四平方和定理:任何自然数都可以用最多四个平方和数之和表示,三平方和定理:只有当4^a*(8b+7)才需要用四个平方和树之和表示
"""
# sol 2:
# BFS广度优先搜索
# runtime: 230ms
if n < 2: return n
# store squared nums <= n
squares = []
i = 1
while i*i <= n:
squares.append(i*i)
i += 1
#
res, lst = 0, {n}
while lst:
res += 1
tem = set()
for i in lst:
for j in squares:
if i==j: return res
elif i < j: break
tem.add(i-j)
lst = tem
return res
dp = [0]
while len(dp) <= n:
dp += min(dp[-i*i] for i in range(1, int(len(dp)**0.5+1))) + 1,
return dp[-1]
127. 单词接龙
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
说明:
- 如果不存在这样的转换序列,返回 0。
- 所有单词具有相同的长度。
- 所有单词只由小写字母组成。
- 字典中不存在重复的单词。
- 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 1:
输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
输出: 5
解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
返回它的长度 5。
示例 2:
输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
输出: 0
解释: endWord "cog" 不在字典中,所以无法进行转换。
class Solution(object):
def ladderLength(self, beginWord, endWord, wordList):
"""
:type beginWord: str
:type endWord: str
:type wordList: List[str]
:rtype: int
"""
wordList = set(wordList)
queue = collections.deque([[beginWord, 1]])
dic = set(string.ascii_lowercase)
while queue:
word, length = queue.popleft()
if word == endWord:
return length
for i in range(len(word)):
for c in dic:
next_word = word[:i] + c + word[i+1:]
if next_word in wordList:
wordList.remove(next_word)
queue.append([next_word, length + 1])
return 0