目录
(2)二叉搜索树(Binary Search Tree,BST)
1、把二叉搜索树转换为累加树
(1)题目
给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。
例如:
输入: 原始二叉搜索树:
5
/ \
2 13
输出: 转换为累加树:
18
/ \
20 13
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/convert-bst-to-greater-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
(2)二叉搜索树(Binary Search Tree,BST)
(又:二叉搜索树,二叉排序树)
它或者是一棵空树,或者是具有下列性质的二叉树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉排序树。
二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。
二叉搜索树的中序遍历结果就是所有结点数据从小到大的排序。
(3)python解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 convertBST(self, root: TreeNode) -> TreeNode:
vallist = []
# 遍历树,取所有值
def bianli(root):
if not root:
return
vallist.append(root.val)
bianli(root.left)
bianli(root.right)
def sum_bianli(root):
if not root:
return
root.val = sum([x for x in vallist if x>root.val]+[root.val])
sum_bianli(root.left)
sum_bianli(root.right)
bianli(root)
sum_bianli(root)
return root
'''
20200921笨拙解法,两次遍历
'''
(4)python解2
依据二叉搜索树的特点,中序遍历就是所有结点val从小到大的排序。
所以最终的思路确定为,反向中序遍历过程中计算遍历数组的前序和,然后更新访问结点的值。
class Solution:
def convertBST(self, root: TreeNode) -> TreeNode:
def reverseInorderVisit(root):
nonlocal res
if not root: return
reverseInorderVisit(root.right)
res += root.val
root.val = res
reverseInorderVisit(root.left)
res = 0
reverseInorderVisit(root)
return root
详细解释:用颜色标记法遍历树
2、监控二叉树
题目
给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。
示例 1:
输入:[0,0,null,0,0]
输出:1
解释:如图所示,一台摄像头足以监控所有节点。
示例 2:
输入:[0,0,null,0,null,0,null,null,0]
输出:2
解释:需要至少两个摄像头来监视树的所有节点。 上图显示了摄像头放置的有效位置之一。
提示:
给定树的节点数的范围是 [1, 1000]。
每个节点的值都是 0。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-cameras
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
python解
思路:状态考虑
除根节点外,每一个节点都是父节点的子节点,所以:
1、根节点没有父节点,要考虑自己
2、非根节点只考虑子节点即可,因为自己会被作为父节点的子节点被考虑到
把节点值当作节点状态:
0:没拍别人也没被拍,需要被人拍
1:被拍了
2:拍别人
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def minCameraCover(self, root: TreeNode) -> int:
self.res = 0
def lrd(node):
if node is None:
return 1 #空节点不需要被人拍也不用拍别人,直接返回被拍了就好
left = lrd(node.left)
right = lrd(node.right)
if left == 0 or right == 0:
#如果左儿子或者右儿子需要被拍,我就装个摄像机
self.res += 1
return 2
if left == 2 or right == 2:
#如果左儿子或者右儿子装了摄像机,那我就被拍了
return 1
else:# left == 1 and right == 1:
#如果左儿子和右儿子都是被拍的,都没有摄像机,那我就是需要被拍的状态
return 0
if lrd(root) == 0:
##看看根节点是不是需要被拍
self.res += 1
return self.res
3、左叶子之和
题目
计算给定二叉树的所有左叶子之和。
示例:
3
/ \
9 20
/ \
15 7
在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sum-of-left-leaves
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
python解
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def sumOfLeftLeaves(self, root:TreeNode) -> int:
res = []
def dfs(root, left, right, res):
if not root:
return
if not root.left and not root.right:
if left and not right:
res.append(root.val)
return
dfs(root.left, True, False, res)
dfs(root.right, False, True, res)
dfs(root, False,False,res)
return sum(res)
4、树的遍历
深度优先(depth first traversal)
对于一颗二叉树,深度优先遍历是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。深度优先遍历有重要的三种方法。这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。这三种遍历分别叫做先序遍历(preorder):根节点->左子树->右子树,中序遍历(inorder):左子树->根节点->右子树,和后序遍历(postorder):左子树->右子树->根节点。这三种都是递归方式实现对一整个二叉树遍历的哦。
广度有先
又称层次遍历,从树的根节点(root)开始,从上到下从从左到右遍历整个树的节点。(利用queue进行遍历)
def breadth_travel(node):
if node == None:
return
else:
# 用队列方式实现遍历,末端按遍历顺序逐个添加节点,首端逐个弹出先读到的结点
queue = []
queue.append(node)
while queue:
cur = queue.pop(0)
print(cur.item, end = " ")
if cur.left is not None:
queue.append(cur.left)
if cur.right is not None:
queue.append(cur.right)
5、合并二叉树
题目
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
示例 1:
输入:
Tree 1 Tree 2
1 2
/ \ / \
3 2 1 3
/ \ \
5 4 7
输出:
合并后的树:
3
/ \
4 5
/ \ \
5 4 7
注意: 合并必须从两个树的根节点开始。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-two-binary-trees
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
python解答:
class Solution:
def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode:
if not t1 or not t2:
return t1 or t2
t1.val = t1.val + t2.val
t1.left = self.mergeTrees(t1.left, t2.left)
t1.right = self.mergeTrees(t1.right, t2.right)
return t1
作者:flyhigher139
链接:https://leetcode-cn.com/problems/merge-two-binary-trees/solution/dfsji-ke-by-flyhigher139/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
6、填充每个节点的下一个右侧节点指针Ⅱ
题目
给定一个二叉树
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解
"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
"""
class Solution:
def connect(self, root:'Node')->'Node'
if root == None:
return root
def BFS(oneLayer):
nextLayer = []
for i in oneLayer:
if i.left:
nextLayer.append(i.left)
if i.right:
nextLayer.append(i.right)
if len(nextLayer)>1:
for j in range(0,len(nextLayer)-1):
nextLayer[j].next = nextLayer[j+1]
if nextlayer:
BFS(nextLayer)
BFS([root])
return root