二叉树
递归算法的关键要明确函数的定义,相信这个定义,而不要跳进递归细节。
写二叉树的算法题,都是基于递归框架的,我们先要搞清楚
root
节点它自己要做什么,然后根据题目要求选择使用前序,中序,后续的递归框架。二叉树题目的难点在于如何通过题目的要求思考出每一个节点需要做什么,这个只能通过多刷题进行练习了。
二叉树遍历框架:
/* 二叉树遍历框架 */
void traverse(TreeNode root) {
// 前序遍历
traverse(root.left)
// 中序遍历
traverse(root.right)
// 后序遍历
}
1,2,3,4,5,6,7
前序遍历:先输出父节点,再遍历左子树和右子树。1, 2, 4, 5, 3, 6, 7
中序遍历:先遍历左子树,在输出父节点,再遍历右子树。4, 2, 5, 1, 6, 3, 7
后序遍历:先遍历左子树,再遍历右子树,最后输出父节点。4, 5, 2, 6, 7, 3, 1
镜像翻转二叉树
这个函数的定义就是给我一个节点,我把他的左右子节点翻转
只去想一个节点翻转需要怎么做,这是一个二叉树的前序遍历
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return root;
}
//翻转
TreeNode tempNode = root.left;
root.left = root.right;
root.right = tempNode;
//子节点也去翻转
invertTree(root.left);
invertTree(root.right);
return root;
}
116. 填充每个节点的下一个右侧节点指针
我辅助函数定义就是将你传给我的两个节点,进行连接。
采用前序遍历,然后需要把这两个节点各自的左右节点连接&&这一个节点的左和一个节点的有连接。
// 主函数
Node connect(Node root) {
if (root == null) return null;
connectTwoNode(root.left, root.right);
return root;
}
// 辅助函数
void connectTwoNode(Node node1, Node node2) {
if (node1 == null || node2 == null) {
return;
}
/**** 前序遍历位置 ****/
// 将传入的两个节点连接
node1.next = node2;
// 连接相同父节点的两个子节点
connectTwoNode(node1.left, node1.right);
connectTwoNode(node2.left, node2.right);
// 连接跨越父节点的两个子节点
connectTwoNode(node1.right, node2.left);
}
114. 二叉树展开为链表
这个函数的定义是:以传给我的头节点的二叉树拉平成一个链表。
进行后序遍历
具体:把他的左右先进行拉平,然后把左树当做右树,左边为null,最后把原来的右树放到现在右树的下面。
// 定义:将以 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;
}
654. 最大二叉树
test函数的定义:返回给定的数组中的最大值new出的节点。
采用前序遍历,
public TreeNode constructMaximumBinaryTree(int[] nums) {
return test(nums, 0, nums.length - 1);
}
public TreeNode test(int[] nums, int start, int end){
if (start > end) {
return null;
}
int index = start;
int max = nums[start];
for (int i = start + 1; i <= end; i++) {
if (max < nums[i]) {
max = nums[i];
index = i;
}
}
TreeNode node = new TreeNode(max);
node.left = test(nums, start, index - 1);
node.right = test(nums, index +1, end);
return node;
}
105. 从前序与中序遍历序列构造二叉树
辅助函数的定义:通过给定的前序,中序数组找到根节点。
流程:根据前序遍历可以知道,根节点就是前序遍历的首位,根节点的下一位就是前序遍历数组的下一位,在通过中序遍历数组就可以确定是左右哪个节点。然后分开去求左右子树。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return test(preorder, 0, preorder.length -1 , inorder, 0 , inorder.length-1);
}
public TreeNode test(int[] preorder,int prestart, int preend, int[] inorder, int instart, int inend) {
if (prestart > preend) {
return null;
}
int index = 0;
for (int i = instart; i <= inend; i++) {
if (preorder[prestart] == inorder[i]) {
index = i;
break