题目介绍
描述:
给你一个树,请你 按中序遍历 重新排列树,使树中最左边的结点现在是树的根,并且每个结点没有左子结点,只有一个右子结点。
示例 :
输入:[5,3,6,2,4,null,8,1,null,null,null,7,9]
5
/ \\
3 6
/ \\ \\
2 4 8
/ / \\
1 7 9
输出:[1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]
1
\\
2
\\
3
\\
4
\\
5
\\
6
\\
7
\\
8
\\
9
提示:
给定树中的结点数介于 1 和 100 之间。
每个结点都有一个从 0 到 1000 范围内的唯一整数值。
解题思路:
递归算法的关键是要明确函数的「定义」是什么,然后相信这个定义,利用这个定义推导最终结果。
写树相关的算法,简单说就是,先搞清楚当前 root 节点该做什么,然后根据函数定义递归调用子节点,递归调用会让孩子节点做相同的事情。
二叉树题目的一个难点在于如何通过题目的要求思考出每一个节点需要做什么
二叉树解题策略
一 递归 二 队列 + 迭代 (层次遍历) 三 栈 + 迭代 (非递归遍历) 四 其它
三种基本的遍历方式,都可以用递归来实现。写递归算法的时候,需要注意递归退出条件以及递归操作的表达。
中序遍历返回升序数组,并根据题目要求的结构生成树。
自己的解法实现
def inorder(node):
if not node: return []
return inorder(node.left) + [node.val] + inorder(node.right)
node_list = inorder(root)
new_root = TreeNode(node_list[0])
cur = new_root
for i in range(1, len(node_list)):
cur.right = TreeNode(node_list[i])
cur = cur.right
return new_root
网上比较优秀的解法
解法一
方法一:中序遍历 + 构造新的树 我们在树上进行中序遍历,就可以从小到大得到树上的节点。我们把这些节点的对应的值存放在数组中,它们已经有序。接着我们直接根据数组构件题目要求的树即可
def increasingBST(self, root):
def inorder(node):
if node:
yield from inorder(node.left)
yield node.val
yield from inorder(node.right)
res = cur = TreeNode(None)
for e in inorder(root):
cur.right = TreeNode(e)
cur = cur.right
return res.right
解法二
方法二:中序遍历 + 更改树的连接方式 我们在树上进行中序遍历,但会将树中的节点之间重新连接而不使用额外的空间。具体地,当我们遍历到一个节点时,把它的左孩子设为空,并将其本身作为上一个遍历到的节点的右孩子。
def increasingBST2(self, root):
def inorder(node):
if node:
inorder(node.left)
node.left = None
self.cur.right = node
self.cur = node
inorder(node.right)
res = self.cur = TreeNode(None)
inorder(root)
return res.right
解法三
这是个很经典的中序遍历的问题。 难点不在递归,而在于如何输出一个只有右子节点的树? 首先要构造一个TreeNode(),再把已有的TreeNode的子节点指向新的TreeNode节点
def increasingBST3(self, root):
def sort(node, ls):
if not node: return
if node.left:
sort(node.left, ls)
ls.append(node.val)
if node.right:
sort(node.right, ls)
res = []
sort(root, res)
ans = cur = TreeNode(None)
for e in res:
cur.val = e
if e == res[-1]:
break
cur.right = TreeNode(None)
cur = cur.right
return ans
相关知识总结和思考
相关知识:
BFS:广度/宽度优先。其实就是从上到下,先把每一层遍历完之后再遍历一下一层。
可以使用Queue的数据结构。我们将root节点初始化进队列,通过消耗尾部,插入头部的方式来完成BFS。
二叉搜索树(BST)的特性:
- 若它的左子树不为空,则所有左子树上的值均小于其根节点的值
- 若它的右子树不为空,则所有右子树上的值均大于其根节点的值
- 它的左右子树也分别为二叉搜索树
递归与迭代的区别
递归:重复调用函数自身实现循环称为递归; 迭代:利用变量的原值推出新值称为迭代,或者说迭代是函数内某段代码实现循环;