二叉树

226. 翻转二叉树


给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

输入:root = [2,1,3]
输出:[2,3,1]

示例 3:

输入:root = []
输出:[]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/invert-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

实例1图:
在这里插入图片描述

实例2图:
在这里插入图片描述


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null){
            return null;
        }

        // 交换 左右节点
        TreeNode tmp;
        tmp = root.left;
        root.left = root.right;
        root.right = tmp;

        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
}

116. 填充每个节点的下一个右侧节点指针


给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

初始状态下,所有 next 指针都被设置为 NULL。

示例 1:

输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。

示例 2:

输入:root = []
输出:[]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

例1图:
在这里插入图片描述


/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;
    public Node next;

    public Node() {}
    
    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, Node _left, Node _right, Node _next) {
        val = _val;
        left = _left;
        right = _right;
        next = _next;
    }
};
*/

class Solution {
    public Node connect(Node root) {
        if (root == null){
            return null;
        }
        connectTwoNode(root.left,root.right);
        return root;
    }
    public void connectTwoNode(Node n1,Node n2){
        if (n1 == null || n2 == null){
            return;
        }
        n1.next = n2; // 将传入的两个节点相连
        connectTwoNode(n1.left,n1.right);
        connectTwoNode(n1.right,n2.left);
        connectTwoNode(n2.left,n2.right);
        return;
    }
}

114. 二叉树展开为链表

***


给你二叉树的根结点 root ,请你将它展开为一个单链表:

    展开后的单链表应该同样使用 TreeNode ,其中 
    right 子指针指向链表中下一个结点,而左子指针始终为 null 。
    展开后的单链表应该与二叉树 先序遍历 顺序相同。

输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [0]
输出:[0]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例1图:
在这里插入图片描述在这里插入图片描述


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public void flatten(TreeNode root) {
        if (root == null){
            return;
        }
        flatten(root.left);
        flatten(root.right);

        // 什么时候会执行这里
        // 左右子树已经被拉平成一条链表
        TreeNode left = root.left;
        TreeNode right = root.right;
        // 将 左子树作为右子树
        root.left = null;
        root.right = left;
        // 将 原先的右子树接到当前右子树的末端
        TreeNode p = root;
        while (p.right != null){
            // 还没有到最末端
            p = p.right;
        }
        p.right = right;

    }
}

654. 最大二叉树


给定一个不重复的整数数组 nums 。 
最大二叉树 可以用下面的算法从 nums 递归地构建:

    1. 创建一个根节点,其值为 nums 中的最大值。
    2. 递归地在最大值 左边 的 子数组前缀上 构建左子树。
    3. 递归地在最大值 右边 的 子数组后缀上 构建右子树。

返回 nums 构建的 最大二叉树 。

 

示例 1:

输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]
解释:递归调用如下所示:
- [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5]- [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1]- 空数组,无子节点。
        - [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1]- 空数组,无子节点。
            - 只有一个元素,所以子节点是一个值为 1 的节点。
    - [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 []- 只有一个元素,所以子节点是一个值为 0 的节点。
        - 空数组,无子节点。

示例 2:

输入:nums = [3,2,1]
输出:[3,null,2,null,1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例1图:
在这里插入图片描述实例2图:
在这里插入图片描述


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        // 遍历 nums,找出最大的元素下标 i ,以 nums[i] 为根节点
        // nums[0]~nums[i-1] 左子树
        // nums[i+1] ~ nums[nums.length] 右子树
        if (nums.length == 0){
            return null;
        }
        TreeNode root = new TreeNode();

        int maxIdx = 0; // nums 中最大元素的下标
        for (int i = 0;i < nums.length;i++){
            if (nums[i] > nums[maxIdx]){
                maxIdx = i;
            }
        }
        root.val = nums[maxIdx];
        int[] leftNums;
        int[] rightNums;
        if (maxIdx != 0){
            leftNums = Arrays.copyOfRange(nums, 0, maxIdx);
        }else {
            leftNums = new int[0];
        }
        if (maxIdx != nums.length){
            rightNums = Arrays.copyOfRange(nums, maxIdx + 1, nums.length);
        }else {
            rightNums = new int[0];
        }

        root.left = constructMaximumBinaryTree(leftNums);
        root.right = constructMaximumBinaryTree(rightNums);

        return root;

    }
}

105. 从前序与中序遍历序列构造二叉树


给定两个整数数组 preorder 和 inorder ,
其中 preorder 是二叉树的先序遍历, 
inorder 是同一棵树的中序遍历,
请构造二叉树并返回其根节点。

示例 1:

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例1 图:
在这里插入图片描述在这里插入图片描述


class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return build(preorder,0,preorder.length-1,
                inorder,0,inorder.length-1);
    }

    TreeNode build(int[] preOrder,int preStart,int preEnd,
                   int[] inOrder,int inStart,int inEnd){

        if (preStart > preEnd){
            // 先序序列没有元素了
            return null;
        }
        TreeNode root = new TreeNode();
        root.val = preOrder[preStart];

        int index = 0;
        for (int i = 0;i <= inEnd;i++){
            if (inOrder[i] == preOrder[preStart]){
                index = i;
                break;
            }
        }
        int leftLength = index - inStart; // 左子树的长度


        root.left = build(preOrder,preStart+1,preStart+leftLength,
                inOrder,inStart,index-1);
        root.right = build(preOrder,preStart+leftLength+1,preEnd,
                inOrder,index+1,inEnd);
        return root;
    }
}

106. 从中序与后序遍历序列构造二叉树


给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

 

示例 1:

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

示例 2:

输入:inorder = [-1], postorder = [-1]
输出:[-1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例2图:
在这里插入图片描述在这里插入图片描述


class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return build(inorder,0,inorder.length-1,
                postorder,0, postorder.length-1);
    }
    public TreeNode build(int[] inorder,int inStart,int inEnd,
                          int[] postorder,int postStart,int postEnd){
        if (inStart > inEnd){
            return null;
        }

        int rootVal = postorder[postEnd];
        TreeNode root = new TreeNode(rootVal);

        int index = 0;
        // 找中序序列 中 root 的索引
        for (int i = 0;i <= inEnd;i++){
            if (inorder[i] == rootVal){
                index = i;
                break;
            }
        }
        int leftLen = index - inStart; // 左子树长度

        root.left = build(inorder,inStart,index-1,
                postorder,postStart,postStart+leftLen-1);
        root.right = build(inorder,index + 1,inEnd,
                postorder,postStart+leftLen,postEnd-1);
        return root;
    }
}

889. 根据前序和后序遍历构造二叉树


给定两个整数数组,preorder 和 postorder ,其中 preorder 是一个具有 无重复 值的二叉树的前序遍历,postorder 是同一棵树的后序遍历,重构并返回二叉树。

如果存在多个答案,您可以返回其中 任何 一个。

示例 1:

输入:preorder = [1,2,4,5,3,6,7], postorder = [4,5,2,6,7,3,1]
输出:[1,2,3,4,5,6,7]

示例 2:

输入: preorder = [1], postorder = [1]
输出: [1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例1图:
在这里插入图片描述在这里插入图片描述前序 + 后序 无法确定一个二叉树
假设前序遍历的第⼆个元素是左⼦树的根节点,但实际上左⼦树可能是空指针,这个元素可能是右⼦树的根节点。
由于这⾥⽆法确切进⾏判断,所以导致了最终答案的不唯⼀。


class Solution {
    public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
        return build(preorder,0,preorder.length-1,
                postorder,0, postorder.length-1);
    }
    public TreeNode build(int[] preorder,int preStart,int preEnd,
                          int[] postorder,int postStart,int postEnd){
        if (preStart > preEnd){
            return null;
        }

        int rootVal = preorder[preStart];
        TreeNode root = new TreeNode(rootVal);

        if (preStart == preEnd){
            return root;
        }
        int leftRootVal = preorder[preStart+1]; // 左子树的根节点的值
        int index = 0; // 左子树的索引
        // 找后序序列 中 root 的索引
        for (int i = 0;i <= postEnd;i++){
            if (postorder[i] == leftRootVal){
                index = i;
                break;
            }
        }

        // preorder 左子树区间:preStart + 1,preStart + leftLen
        // postorder 左子树区间:postStart , index
        // preorder 右子树区间:preStart + leftLen + 1,preEnd
        // preorder 右子树区间:index + 1, postEnd - 1
        int leftLen = index - postStart + 1; // 左子树长度

        root.left = build(preorder,preStart + 1,preStart + leftLen,
                postorder,postStart , index);
        root.right = build(preorder,preStart + leftLen + 1,preEnd,
                postorder,index + 1, postEnd - 1);
        return root;
    }

}

652. 寻找重复的子树


给定一棵二叉树 root,返回所有重复的子树。

对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。

如果两棵树具有相同的结构和相同的结点值,则它们是重复的。

 
示例 1:

输入:root = [1,2,3,4,null,2,4,null,null,4]
输出:[[2,4],[4]]

示例 2:

输入:root = [2,1,1]
输出:[[1]]

示例 3:

输入:root = [2,2,2,3,null,3,null]
输出:[[2,3],[3]]

 

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-duplicate-subtrees
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例1:
在这里插入图片描述

示例2:
在这里插入图片描述

示例3:
在这里插入图片描述


297. 二叉树的序列化与反序列化


序列化是将一个数据结构或者对象转换为连续的比特位的操作,
进而可以将转换后的数据存储在一个文件或者内存中,
同时也可以通过网络传输到另一个计算机环境,
采取相反方式重构得到原数据。

请设计一个算法来实现二叉树的序列化与反序列化。
这里不限定你的序列 / 反序列化算法执行逻辑,
你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。

提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。

 

示例 1:

输入:root = [1,2,3,null,null,4,5]
输出:[1,2,3,null,null,4,5]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

示例 4:

输入:root = [1,2]
输出:[1,2]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


中间确实很多BST、二叉树的序列化与反序列化

104. 二叉树的最大深度


给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null){
            return 0;
        }
        int depthLeft = maxDepth(root.left);
        int depthRight = maxDepth(root.right);
        return Math.max(depthLeft,depthRight)+1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值