剑指offer-二叉树
1. 平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
解:
要么是一颗空树,要么左右子树都是平衡二叉树且左右子树深度之差不超过1
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 def IsBalanced_Solution(self, pRoot):
8 # write code here
9 if not pRoot:
10 return True
11 res = abs(self.getDepth(pRoot.left) - self.getDepth(pRoot.right))
12 if res <= 1 and self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right):
13 return True
14 return False
15
16 def getDepth(self, root):
17 if not root:
18 return 0
19 if not (root.left or root.right):
20 return 1
21 return max(self.getDepth(root.left), self.getDepth(root.right)) + 1
2. 二叉树的深度
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
解:
层次遍历,bfs 实现
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 def TreeDepth(self, pRoot):
8 # write code here
9 if not pRoot:
10 return 0
11 depth = 0
12 queue = [pRoot]
13 while queue:
14 tmp = []
15 for i in range(len(queue)):
16 node = queue.pop(0)
17 tmp.append(node.val)
18 if node.left:
19 queue.append(node.left)
20 if node.right:
21 queue.append(node.right)
22 if tmp:
23 depth += 1
24 return depth
dfs 实现,只需要记录深度即可,不用记录节点
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 def TreeDepth(self, pRoot):
8 # write code here
9 if not pRoot:
10 return 0
11 self.depth = 0
12 def helper(node, level):
13 if not(node.left or node.right):
14 self.depth = max(self.depth, level)
15 return
16 if node.left:
17 helper(node.left, level+1)
18 if node.right:
19 helper(node.right, level+1)
20
21 helper(pRoot, 1)
22 return self.depth
3. 二叉树的下一个节点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
解:
几种可能的情况考虑一下即可
1 # class TreeLinkNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 # self.next = None
7 class Solution:
8 def GetNext(self, pNode):
9 # write code here
10 if not pNode:
11 return
12
13 # 如果当前节点有右子树,中序遍历的下一个节点是其右子树的最左节点
14 if pNode.right:
15 pRight = pNode.right
16 while pRight.left:
17 pRight = pRight.left
18 return pRight
19
20 # 如果当前节点没有右子树,但是当前节点是其父节点的左子节点,下一个节点是其父节点
21 if pNode.next and pNode.next.left == pNode:
22 return pNode.next
23
24 # 如果当前节点没有右子树,但是是其父节点的右子节点,则一直向上遍历,找到是其父节点的左子结点的pNode
25 # 当前节点的下一个节点就是pNode的父节点
26 if pNode.next and pNode.next.right == pNode:
27 while pNode.next and pNode != pNode.next.left:
28 pNode = pNode.next
29 return pNode.next
30 return
4. 对称的二叉树
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
解:
递归实现,判断给定两个节点为根的子树是否镜像,首先根节点的值要相等,其次A的左子树和B的右子树、A的右子树和B的左子树要递归的进行判断
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 def isSymmetrical(self, pRoot):
8 # write code here
9 if not pRoot:
10 return True
11 return self.compare(pRoot.left, pRoot.right)
12
13 def compare(self, p1, p2):
14 if p1 == None :
15 return p2 == None
16 if p2 == None:
17 return False
18 if p1.val != p2.val:
19 return False
20 return self.compare(p1.left, p2.right) and self.compare(p1.right, p2.left)
dfs,用栈实现,成对取出成对插入,镜像:左左配右右,左右配右左
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 def isSymmetrical(self, pRoot):
8 # write code here
9 if not pRoot:
10 return True
11 stack = [pRoot.left, pRoot.right]
12
13 while stack:
14 right = stack.pop() # 成对取出
15 left = stack.pop()
16 if left == None and right == None:
17 continue
18 if left == None or right == None:
19 return False
20 if left.val != right.val:
21 return False
22
23 # 成对插入
24 stack.append(left.left)
25 stack.append(right.right)
26 stack.append(left.right)
27 stack.append(right.left)
28
29 return True
bfs,队列实现
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 def isSymmetrical(self, pRoot):
8 # write code here
9 if not pRoot:
10 return True
11 queue = [pRoot.left, pRoot.right]
12
13 while queue:
14 left = queue.pop(0) # 成对取出
15 right = queue.pop(0)
16 if left == None and right == None:
17 continue
18 if left == None or right == None:
19 return False
20 if left.val != right.val:
21 return False
22
23 # 成对插入
24 queue.append(left.left)
25 queue.append(right.right)
26 queue.append(left.right)
27 queue.append(right.left)
28
29 return True
5. 把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
解:
层次遍历,bfs
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 # 返回二维列表[[1,2],[4,5]]
8 def Print(self, pRoot):
9 # write code here
10 if not pRoot:
11 return []
12 res = []
13 queue = [pRoot]
14 while queue:
15 tmp = []
16 for i in range(len(queue)):
17 node = queue.pop(0)
18 tmp.append(node.val)
19 if node.left:
20 queue.append(node.left)
21 if node.right:
22 queue.append(node.right)
23 if tmp:
24 res.append(tmp)
25 return res
dfs
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 # 返回二维列表[[1,2],[4,5]]
8 def Print(self, pRoot):
9 # write code here
10 if not pRoot:
11 return []
12 self.res = []
13
14 def helper(node, level):
15 if not node:
16 return
17 if level == len(self.res):
18 self.res.append([])
19 self.res[level].append(node.val)
20 if node.left:
21 helper(node.left, level + 1)
22 if node.right:
23 helper(node.right, level + 1)
24
25 helper(pRoot, 0)
26 return self.res
6. 按之字形顺序打印二叉树
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
解:
还是层次遍历,用一个 flag 控制每一层是正序还是逆序
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 def Print(self, pRoot):
8 # write code here
9 if not pRoot:
10 return []
11 leftToRight = True
12 queue = [pRoot]
13 res = []
14 while queue:
15 tmp = []
16 for i in range(len(queue)):
17 node = queue.pop(0)
18 tmp.append(node.val)
19 if node.left:
20 queue.append(node.left)
21 if node.right:
22 queue.append(node.right)
23 if tmp:
24 if leftToRight:
25 res.append(tmp)
26 else:
27 res.append(tmp[::-1])
28 leftToRight = not leftToRight
29 return res
7. 序列化二叉树
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 def __init__(self):
8 self.flag = -1
9 def Serialize(self, root):
10 # write code here
11 if not root:
12 return '#!'
13 return str(root.val)+'!'+self.Serialize(root.left)+self.Serialize(root.right)
14
15 def Deserialize(self, s):
16 # write code here
17 self.flag += 1
18 vals = s.split('!')
19 if self.flag >= len(vals):
20 return None
21 root = None
22 if vals[self.flag] != '#':
23 root = TreeNode(int(vals[self.flag]))
24 root.left = self.Deserialize(s)
25 root.right = self.Deserialize(s)
26 return root
8. 二叉搜索树的第k个节点
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
解:
中序遍历即有序
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 # 返回对应节点TreeNode
8 def KthNode(self, pRoot, k):
9 # write code here
10 if not pRoot:
11 return None
12 self.res = []
13 self.midOrdTrav(pRoot)
14 return self.res[k-1] if 0<k<=len(self.res) else None
15
16 def midOrdTrav(self, root):
17 if not root:
18 return
19 self.midOrdTrav(root.left)
20 self.res.append(root)
21 self.midOrdTrav(root.right)
中序遍历的时候维护一个计数器,到 k 个数了就返回
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 # 返回对应节点TreeNode
8 def KthNode(self, pRoot, k):
9 # write code here
10 if not pRoot:
11 return None
12
13 count = 0
14 stack = []
15 p = pRoot
16 while p or stack:
17 while p:
18 stack.append(p)
19 p = p.left
20 if stack:
21 p = stack.pop()
22 count += 1
23 if count == k:
24 return p
25 p = p.right
26 return None
1 import heapq
2 class Solution:
3 def __init__(self):
4 self.small = [] # 小的数,大顶堆
5 self.large = [] # 大的数,小顶堆
6
7 def Insert(self, num):
8 # write code here
9 heapq.heappush(self.small, -heapq.heappushpop(self.large, num))
10 if len(self.large) < len(self.small):
11 heapq.heappush(self.large, -heapq.heappop(self.small))
12
13 def GetMedian(self, default=None):
14 # write code here
15 if len(self.large) > len(self.small):
16 return float(self.large[0])
17 return (self.large[0] - self.small[0])/2.
1 # class TreeNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.left = None
5 # self.right = None
6 class Solution:
7 # 返回构造的TreeNode根节点
8 def reConstructBinaryTree(self, pre, tin):
9 # write code here
10 if not pre or not tin:
11 return None
12 root = TreeNode(pre[0])
13 index = self.Search(tin, root.val) # tin.index(root.val)
14 root.left = self.reConstructBinaryTree(pre[1:index+1], tin[:index])
15 root.right = self.reConstructBinaryTree(pre[index+1:], tin[index+1:])
16 return root
17
18 def Search(self, nums, target):
19 if not nums:
20 return -1
21 n = len(nums)
22 for i in range(n):
23 if nums[i] == target:
24 return i
25 return -1
剑指offer-二叉树的更多相关文章
- 剑指Offer——二叉树
剑指Offer--二叉树 前言 数据结构通常是编程面试中考察的重点.在参加面试之前,应聘者需要熟练掌握链表.树.栈.队列和哈希表等数据结构,以及它们的操作.本片博文主要讲解二叉树操作的相关知识,主要包 ...
- 剑指offer 二叉树中和为某一个值的路径
剑指offer 牛客网 二叉树中和为某一个值的路径 # -*- coding: utf-8 -*- """ Created on Tue Apr 9 15:53:58 2 ...
- 剑指offer 二叉树的层序遍历
剑指offer 牛客网 二叉树的层序遍历 # -*- coding: utf-8 -*- """ Created on Tue Apr 9 09:33:16 2019 @ ...
- JS数据结构与算法 - 剑指offer二叉树算法题汇总
❗❗ 必看经验 在博主刷题期间,基本上是碰到一道二叉树就不会碰到一道就不会,有时候一个下午都在搞一道题,看别人解题思路就算能看懂,自己写就呵呵了.一气之下不刷了,改而先去把二叉树的基础算法给搞搞懂,然 ...
- 剑指offer——二叉树的镜像
题目:操作给定的二叉树,将其变换为源二叉树的镜像. 思路:前序(根左右的顺序)遍历一棵树,在存储的时候将其左右树进行交换,最后按照处理后的树还原,即得到其镜像. /** public class Tr ...
- 剑指Offer 二叉树中和为某一值的路径(dfs)
题目描述 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 思路: 递归,然后深搜,因为题目定义的, ...
- 剑指Offer 二叉树的镜像
题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ ...
- 剑指Offer——二叉树的下一个结点
题目描述: 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 分析: 如果该结点存在右子树,那么返回右子树的最左结 ...
- 剑指Offer——二叉树的深度
题目描述: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 分析: 二叉树的深度等于其左子树的深度和右子树的深度两个中最大的深 ...
- 剑指Offer——二叉树中和为某一值的路径
题目描述: 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 分析: 先序遍历二叉树,找到二叉树中结点值的和 ...
随机推荐
- Java面试题(容器篇)
容器 18.java 容器都有哪些? 如图: 首先分为Collection.Map: Collection下分为List.Set和Queue: List下分为ArrayList和LinkedLis ...
- mybatis逆向工程介绍
项目的model一旦多了起来,复杂了起来,我们很自然的想到使用mybatis的逆向工程来生成相应的pojo和mapper,能节省很多精力. MyBatis Generator(MBG)是 MyBati ...
- Htmlcss学习笔记2——选择器与常用样式
CSS引入类型 行内样式 内联样式 外部样式表 CSS选择器 基本选择器 复合选择器 伪类选择器 属性选择器 CSS字体样式 font-size font-family font-style font ...
- 有手就行 虚拟机上安装Linux
VMware上装Linux CentOS 初学一步步来
- Math Problem(数学)
链接:https://ac.nowcoder.com/acm/contest/893/C来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K ...
- Tomcat9w.exe无法启动为started
问题: startup.bat可以正常启动,http://localhost:8080/ 可以正常访问.但是Tomcat9w.exe无法启动为started,一直为Stopped. 解决方案: 如下图 ...
- 20190923-01Linux帮助命令 000 009
man 获得帮助信息 1. 基本语法 man [命令或配置文件] (功能描述:获得帮助信息) 2.显示说明 表1-6 信息 功能 NAME 命令的名称和单行描述 SYNOPSIS 怎样使用命令 DES ...
- vue-axios拦截器
"use strict"; import QS from "qs"; import Axios from "axios"; import s ...
- docker中重启某个服务命令
docker ps------查看正在运行的cotainners docker ps -a --------查看所有的containners docker restart 容器id docker lo ...
- 小程序开发-iView Weapp微信小程序UI组件库入门使用
iView Weapp UI组件库 今天来试试iView Weapp 这个微信小程序组件库,看看好不好用~~ 官网地址: http://inmap.talkingdata.com/wx/index_p ...