从二叉树学递归思想
写递归算法的关键是要明确函数的「定义」是什么,然后相信这个定义,利用这个定义推导最终结果,绝不要试图跳入递归。
统计二叉树节点个数
// 定义:count(root) 返回以 root 为根的树有多少节点
int count(TreeNode root) {
// base case
if (root == null) return 0;
// 自己加上子树的节点数就是整棵树的节点数
return 1 + count(root.left) + count(root.right);
}
写树相关的算法,简单说就是,先搞清楚当前root节点该做什么,然后根据函数定义递归调用子节点,递归调用会让孩子节点做相同的事情。
翻转或者镜像二叉树
二叉树题目的一个难点就是,如何把题目的要求细化成每个节点需要做的事情。
// 将整棵树的节点翻转
TreeNode invertTree(TreeNode root) {
// base case
if (root == null) {
return null;
}
/**** 前序遍历位置 ****/
// root 节点需要交换它的左右子节点
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
// 让左右子节点继续翻转它们的子节点
invertTree(root.left);
invertTree(root.right);
return root;
}
填充每个节点的下一个右侧节点指针
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:return
# 辅助函数
def connectTwoNode(node1, node2):
if not node1 or not node2:return
node1.next = node2
connectTwoNode(node1.left, node1.right)
connectTwoNode(node2.left, node2.right)
connectTwoNode(node1.right, node2.left)
connectTwoNode(root.left,root.right)
return root
将二叉树展开为链表
// 定义:将以 root 为根的树拉平为链表
void flatten(TreeNode root) {
// base case
if (root == null) return;
flatten(root.left);
flatten(root.right);
/**** 后序遍历位置 ****/
// 1、左右子树已经被拉平成一条链表
TreeNode left = root.left;
TreeNode right = root.right;
// 2、将左子树作为右子树
root.left = null;
root.right = left;
// 3、将原先的右子树接到当前右子树的末端
TreeNode p = root;
while (p.right != null) {
p = p.right;
}
p.right = right;
}
只要知道flatten的定义如此,相信这个定义,让root做它该做的事情,然后flatten函数就会按照定义工作。
树算法思想
把题目的要求细化,搞清楚根节点应该做什么,然后剩下的事情抛给前/中/后序的遍历框架就行