python 树 数据结构_剑指Offer数据结构之树[Python版]

面试题004 重建二叉树

题目描述:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

解题思路:

递归思想。前序遍历中第一个元素是根,因此在中序遍历中找到根的位置下标,根将中序遍历分为两部分,分别是左子树和右子树,然后继续递归寻找左右子树的根节点。

代码:

class Solution:

# 返回构造的TreeNode根节点

def reConstructBinaryTree(self, pre, tin):

# write code here

if not pre or not tin:

return None

root = TreeNode(pre[0])

index = tin.index(pre[0])

root.left = self.reConstructBinaryTree(pre[1:1+index],tin[:index])

root.right = self.reConstructBinaryTree(pre[1+index:],tin[1+index:])

return root

面试题017 树的子结构

题目描述:

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

解题思路:判断A和B的根是否相同,如果不同的话,将A的左子树和右子树再与B做判断;如果相同的话,则判断子树是否相同:比较每个节点,有一个不相同则不相同

代码

class Solution:

def HasSubtree(self, pRoot1, pRoot2):

# write code here

result = False

if pRoot1 and pRoot2:

if pRoot1.val==pRoot2.val:

result = self.DoesTree1HaveTree2(pRoot1,pRoot2)

if not result:

result = self.HasSubtree(pRoot1.left,pRoot2)

if not result:

result = self.HasSubtree(pRoot1.right,pRoot2)

return result

def DoesTree1HaveTree2(self,pRoot_A,pRoot_B):

if not pRoot_B:

return True

if not pRoot_A:

return False

if pRoot_A.val != pRoot_B.val:

return False

return self.DoesTree1HaveTree2(pRoot_A.left,pRoot_B.left) and self.DoesTree1HaveTree2(pRoot_A.right,pRoot_B.right)

面试题018 二叉树的镜像

题目描述:操作给定的二叉树,将其变换为源二叉树的镜像。

示例:

二叉树的镜像定义:源二叉树

8

/

6 10

/ \ /

5 7 9 11

镜像二叉树

8

/

10 6

/ \ /

11 9 7 5

解题思路:将二叉树的每个子树的左右节点交换位置就可以得到二叉树的镜像,由于每一层的树操作都是一样的,所以使用递归求解。

代码

class Solution:

# 返回镜像树的根节点

def Mirror(self, root):

# write code here

if not root:

return root

node = root.left

root.left = root.right

root.right = node

self.Mirror(root.left)

self.Mirror(root.right)

return root

面试题022 从上往下打印二叉树

题目描述:从上往下打印出二叉树的每个节点,同层节点从左至右打印。

解题思路:二叉树层次遍历,用队列存储每层结点,再依次弹出

代码

class Solution:

# 返回从上到下每个节点值列表,例:[1,2,3]

def PrintFromTopToBottom(self, root):

# write code here

if not root:

return []

quene = []

result = []

quene.append(root)

while len(quene)>0:

node = quene.pop(0)

result.append(node.val)

if node.left:

quene.append(node.left)

if node.right:

quene.append(node.right)

return result

面试题023 二叉搜索树的后序遍历

题目描述:输入一个非空整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

解题思路:

已知条件:后序遍历最后一个值为root;二叉搜索树左子树值都比root小,右子树值都比root大。

1、确定root;

2、遍历序列(除去root结点),找到第一个大于root的位置,则该位置左边为左子树,右边为右子树;

3、遍历右子树,若发现有小于root的值,则直接返回false;

4、分别判断左子树和右子树是否仍是二叉搜索树(即递归步骤1、2、3)

代码

class Solution:

def VerifySquenceOfBST(self, sequence):

# write code here

if not sequence:

return False

return self.helper(sequence)

def helper(self, sequence):

if not sequence:

return True

root = sequence[-1]

for i in range(len(sequence)):

if sequence[i] > root:

break

for right in sequence[i:-1]:

if right < root:

return False

return self.helper(sequence[:i]) and self.helper(sequence[i:-1])

面试题024 二叉树中和为某一值得路径

题目描述:输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

解题思路:前序遍历,每次访问一个节点就将当前权值求和,如果当前权值和期待值一致,就保存,每次深度遍历到底部

代码

class Solution:

# 返回二维列表,内部每个列表表示找到的路径

def FindPath(self, root, expectNumber):

# write code here

if not root:

return []

if root and not root.left and not root.right and root.val==expectNumber:

return [[root.val]]

res = []

left = self.FindPath(root.left, expectNumber-root.val)

right = self.FindPath(root.right, expectNumber-root.val)

for i in left+right:

res.append([root.val]+i)

res = sorted(res,key=lambda x:len(x),reverse=True)

return res

面试题026 二叉搜索树与双向链表

题目描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

解题思路:From leetcode

解法基于性质:二叉搜索树的中序遍历为 递增序列 。

将二叉搜索树转换成一个 “排序的循环双向链表” ,其中包含三个要素:

排序链表: 节点应从小到大排序,因此应使用 中序遍历 “从小到大”访问树的节点;

双向链表: 在构建相邻节点(设前驱节点 prepre ,当前节点 curcur )关系时,不仅应 pre.right = curpre.right=cur ,也应 cur.left = precur.left=pre 。

循环链表: 设链表头节点 headhead 和尾节点 tailtail ,则应构建 head.left = tailhead.left=tail 和 tail.right = headtail.right=head 。

根据以上分析,考虑使用中序遍历访问树的各节点 curcur ;并在访问每个节点时构建 curcur 和前驱节点 prepre 的引用指向;中序遍历完成后,最后构建头节点和尾节点的引用指向即可。

代码

class Solution(object):

def treeToDoublyList(self, root):

"""

:type root: Node

:rtype: Node

"""

def dfs(cur):

if not cur: return

dfs(cur.left) # 递归左子树

if self.pre: # 修改节点引用

self.pre.right, cur.left = cur, self.pre

else: # 记录头节点

self.head = cur

self.pre = cur # 保存 cur

dfs(cur.right) # 递归右子树

if not root: return

self.pre = None

dfs(root)

self.head.left, self.pre.right = self.pre, self.head

return self.head

解题思路:二叉树的中序遍历

中序遍历中每个结点的链接

代码

class Solution:

def Convert(self, pRootOfTree):

if not pRootOfTree:

return None

p = pRootOfTree

stack = []

resStack = []

while p or stack:

if p:

stack.append(p)

p = p.left

else:

node = stack.pop()

resStack.append(node)

p = node.right

resP = resStack[0]

while resStack:

top = resStack.pop(0)

if resStack:

top.right = resStack[0]

resStack[0].left = top

return resP

解题思路:递归

class Solution:

def Convert(self, root):

if not root:

return None

if not root.left and not root.right:

return root

# 将左子树构建成双链表,返回链表头

left = self.Convert(root.left)

p = left

# 定位至左子树的最右的一个结点

while left and p.right:

p = p.right

# 如果左子树不为空,将当前root加到左子树链表

if left:

p.right = root

root.left = p

# 将右子树构造成双链表,返回链表头

right = self.Convert(root.right)

# 如果右子树不为空,将该链表追加到root结点之后

if right:

right.left = root

root.right = right

return left if left else root

面试题038 二叉树的深度

题目描述:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

解题思路:一棵二叉树的深度是其左子树和右子树深度的最大值+1。拿左子树的深度来讲,左子树的深度等于其左右子树深度的最大值+1。递归这一过程即可

求树的深度,可以从层次遍历出发考虑,层次遍历可以使用队列完成,也可以使用递归完成

代码

方法一:使用队列

class Solution:

# 层次遍历

def levelOrder(self, root):

# write your code here

# 存储最后层次遍历的结果

res = []

# 层数

count = 0

# 如果根节点为空,则返回空列表

if root is None:

return count

# 模拟一个队列储存节点

q = []

# 首先将根节点入队

q.append(root)

# 列表为空时,循环终止

while len(q) != 0:

# 使用列表存储同层节点

tmp = []

# 记录同层节点的个数

length = len(q)

for i in range(length):

# 将同层节点依次出队

r = q.pop(0)

if r.left is not None:

# 非空左孩子入队

q.append(r.left)

if r.right is not None:

# 非空右孩子入队

q.append(r.right)

tmp.append(r.val)

if tmp:

count += 1  # 统计层数

res.append(tmp)

return count

def TreeDepth(self, pRoot):

# write code here

# 使用层次遍历

# 当树为空直接返回0

if pRoot is None:

return 0

count = self.levelOrder(pRoot)

return count

方法二:使用递归方法

class Solution:

def TreeDepth(self, pRoot):

# write code here

# 使用层次遍历

# 当树为空直接返回0

if pRoot is None:

return 0

# 方法2:使用递归

# 如果该树只有一个结点,它的深度为1.如果根节点只有左子树没有右子树,

# 那么树的深度为左子树的深度加1;同样,如果只有右子树没有左子树,

# 那么树的深度为右子树的深度加1。如果既有左子树也有右子树,

# 那该树的深度就是左子树和右子树的最大值加1.

count = max(self.TreeDepth(pRoot.left), self.TreeDepth(pRoot.right)) + 1

return count

面试题039 平衡二叉树

题目描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。

一棵高度平衡二叉树定义:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。

解题思路:

方法一:自顶向下,对于每个节点,都计算一下左子树以及右子树的差的绝对值,即每个节点都判断一下。

算法复杂度为O(N*2)

代码

class Solution:

def IsBalanced_Solution(self, pRoot):

# write code here

if not pRoot:

return True

left = self.depth(pRoot.left)

right = self.depth(pRoot.right)

return abs(left - right) <= 1 and self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)

def depth(self, pRoot):

if not pRoot:

return 0

return 1 + max(self.depth(pRoot.left), self.depth(pRoot.right))

方法二:自下往上 算法复杂度O(N)

代码:

# -*- coding:utf-8 -*-

# class TreeNode:

#     def __init__(self, x):

#         self.val = x

#         self.left = None

#         self.right = None

class Solution:

def IsBalanced_Solution(self, p):

return self.dfs(p) != -1

def dfs(self, p):

if p is None:

return 0

left = self.dfs(p.left)

if left == -1:

return -1

right = self.dfs(p.right)

if right == -1:

return -1

if abs(left - right) > 1:

return -1

return max(left, right) + 1

面试题057 二叉树的下一个结点

题目描述:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

解题思路:中序遍历的规则是:左根右

分成两大类:1、有右子树的,那么下个结点就是右子树最左边的点;(eg:D,B,E,A,C,G) 2、没有右子树的,也可以分成两类,a)是父节点左孩子(eg:N,I,L) ,那么父节点就是下一个节点 ; b)是父节点的右孩子(eg:H,J,K,M)找他的父节点的父节点的父节点...直到当前结点是其父节点的左孩子位置。如果没有eg:M,那么他就是尾节点。

代码

class Solution:

def GetNext(self, pNode):

# write code here

if pNode.right:#有右子树

p=pNode.right

while p.left:

p=p.left

return p

while pNode.next:#无右子树,则找第一个当前节点是父节点左孩子的节点

if(pNode.next.left==pNode):

return pNode.next

pNode = pNode.next#沿着父节点向上遍历

return None #到了根节点仍没找到,则返回空

面试题058 对称的二叉树

题目描述:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

1

/

2 2

/ \ /

3 4 4 3

输入:root = [1,2,2,3,4,4,3]

输出:true

解题思路:简单DFS

镜像也就是左右子树的左右节点值是否相等,通过比较即可得出结果

代码

class Solution:

def isSymmetrical(self, pRoot):

# write code here

if not pRoot:

return True

def isSyt(left_,right_):

if not left_ and not right_:#节点都为空,也是对称的

return True

elif left_ and right_:#都不为空

if left_.val != right_.val:#不为空且不相等则不是对称的

return False

else:

return isSyt(left_.right, right_.left) and isSyt(left_.left, right_.right)#遍历左右子树

else:#一个节点为空一个节点不为空

return False

return isSyt(pRoot.left, pRoot.right)

简化版

class Solution:

def isSymmetrical(self, pRoot):

# write code here

def recur(L, R):

if not L and not R: return True

if not L or not R or L.val != R.val: return False

return recur(L.left, R.right) and recur(L.right, R.left)

return recur(pRoot.left, pRoot.right) if pRoot else True

面试题059

题目描述:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

解题思路:层序打印,和按层打印的唯一区别是是否需要将当前层打印倒置。

代码

class Solution:

def Print(self, pRoot):

# write code here

if not pRoot: return []

res, roots = [], [pRoot]

while roots:

tmp = []

for _ in range(len(roots)):

r = roots.pop(0)

tmp.append(r.val)

if r.left: roots.append(r.left)

if r.right: roots.append(r.right)

if len(res) & 1: tmp.reverse()

res.append(tmp)

return res

面试题060 把二叉树打印成多行

题目描述:从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

解题思路:层序打印

代码

class Solution:

# 返回二维列表[[1,2],[4,5]]

def Print(self, pRoot):

# write code here

if not pRoot:

return []

res, roots = [], [pRoot]

while roots:

temp = []

for _ in range(len(roots)):

r = roots.pop(0)

temp.append(r.val)

if r.left: roots.append(r.left)

if r.right: roots.append(r.right)

res.append(temp)

return res

面试题061 序列化二叉树

题目描述:请实现两个函数,分别用来序列化和反序列化二叉树

示例: 将以下二叉树:

1

/

2 3

/

4 5

序列化为 "[1,2,3,null,null,4,5]"

解题思路:From 剑指offer

递归实现二叉树前序遍历,前序遍历实现序列化与反序列化

代码

class TreeNode:

def __init__(self, x):

self.val = x

self.left = None

self.right = None

class Solution:

def Serialize(self, root):

# write code here

if root is None:

return '#'

return str(root.val) + '!' + self.Serialize(root.left) + '!' + self.Serialize(root.right)

def Deserialize(self, s):

# write code

def deserialize(ls):

if len(s) <= 0:

return None

root = None

val = ls.pop(0)

if val != '#':

root = TreeNode(int(val))

root.left = deserialize(ls)

root.right = deserialize(ls)

return root

arr = s.split('!')

return deserialize(arr)

面试题062 二叉搜索树的第k个结点

题目描述:给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

解题思路:中序遍历第k个数

代码

class Solution:

# 返回对应节点TreeNode

def KthNode(self, pRoot, k):

# write code here

if not pRoot:

return None

stack = []

while pRoot or stack:

while pRoot:

stack.append(pRoot)

pRoot = pRoot.left

pRoot = stack.pop()

k -= 1

if k == 0:

return pRoot

pRoot = pRoot.right

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值