《剑指offer》python实现系列,全目录

第一想法:二叉树的广度优先遍历


14class Solution:
def PrintFromTopToBottom(self, root):
elemlist = []
if root is None:
return elemlist
queue = [root] #使用队列
while queue:
cur = queue.pop(0)
elemlist.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
return elemlist

升级版题目二:要求分行打印二叉树

8 8
6 10 分行打印 ==》 6 10
5 7 9 11 5 7 9 11

方法:添加两个辅助变量,记录当前行待打印的节点数目toBePrintNum和下一行的节点个数nextLevelNum


30class Solution:
# 返回二维列表[[1,2],[4,5]]
def Print(self, pRoot):
if pRoot is None:
return []
elemlist = []
levelElem = [] #一行的结点值
queue = [pRoot]#队列存储待处理结点
toBePrintNum = 1 #当前行待打印的节点数目
nextLevelNum = 0 #下一行节点数目
while queue:
curNode = queue.pop(0)
levelElem.append(curNode.val)
toBePrintNum -= 1
#若左存在,下一行节点数目+1,右孩子存在,下一行节点数目+1
if curNode.left:
queue.append(curNode.left)
nextLevelNum += 1
if curNode.right:
queue.append(curNode.right)
nextLevelNum += 1
if toBePrintNum == 0: #这一层的结点打印完了
elemlist.append(levelElem)
levelElem = [] #清空
toBePrintNum = nextLevelNum#更新为下一层节点数
nextLevelNum = 0
return elemlist

升级版题目三:之字形打印二叉树

第一行按从左到右,第二行按从右到左,第三行按从左到右

8 8
6 10 分行打印 ==》 10 6
5 7 9 11 11 9 7 5

第一想法:在题目二的基础上,加一个reverseFlag,用于判断是否将levelElem进行reverse操作。

奇数行不reverse,偶数行reverse


35class Solution:
def Print(self, pRoot):
if pRoot is None:
return []
reverseFlag = 1 #levlelElem[]是否需要reverse的flag,大于0表示不翻转
elemlist = []
levelElem = [] #一行的结点值
queue = [pRoot]#队列存储待处理结点
toBePrintNum = 1 #当前行待打印的节点数目
nextLevelNum = 0 #下一行节点数目
while queue:
curNode = queue.pop(0)
levelElem.append(curNode.val)
toBePrintNum -= 1
#若左存在,下一行节点数目+1,右孩子存在,下一行节点数目+1
if curNode.left:
queue.append(curNode.left)
nextLevelNum += 1
if curNode.right:
queue.append(curNode.right)
nextLevelNum += 1
if toBePrintNum == 0: #这一层的结点打印完了
if reverseFlag < 0:
levelElem.reverse()
reverseFlag *= (-1) #每处理完一行就更新
elemlist.append(levelElem)
levelElem = [] #清空
toBePrintNum = nextLevelNum#更新为下一层节点数
nextLevelNum = 0
return elemlist

剑指offer方法:感觉不如我的


2 3 【1.l 1.r 】
4 5 6 7 【3.r 3.l 2.r 2.l】
8 9 10 11 12 13 14 15 【4.l 4.r 5.l 5.r 6.l 6.r 7.l 7.r】

curNodeList记录当前层结点

利用栈的后进先出,添加一个辅助栈nextNodeStack,保存当前层每个结点的下一层的结点。

若待保存的是奇数层的子节点,先保存左孩再保存右孩子到nextStack栈里;

若打印的是偶数层的子节点,先保存右孩子再保存左孩子到nextStack栈里;

赋予curNodeList,nextStack清空,继续处理下一层。


34class Solution:
def Print(self, pRoot):
if pRoot is None:
return []
isOddFlag = 1 #当前行是否是奇数行
curNodeList = [pRoot]
elemlist = []
while curNodeList:#每个while循环处理完当前行
nextNodeStack = [] #记录下一行的结点
levelElemlist = [] #存储当前行的结点值
if isOddFlag>0:#当前行是奇数行
for node in curNodeList:
levelElemlist.append(node.val)
#处理此行的子节点,先push左孩子再push右孩子
if node.left:
nextNodeStack.append(node.left)
if node.right:
nextNodeStack.append(node.right)
else:
for node in curNodeList:
levelElemlist.append(node.val)
#处理此行的子节点,先push右孩子再push左孩子
if node.right:
nextNodeStack.append(node.right)
if node.left:
nextNodeStack.append(node.left)
elemlist.append(levelElemlist)
levelElemlist = []
isOddFlag *= -1
nextNodeStack.reverse() #模拟栈先进后出,将list翻转就是先进后出了
curNodeList = nextNodeStack
return elemlist