Leetcode刷题——树篇5

5、树(中等篇1)

5.1、1379. 找出克隆二叉树中的相同节点

给你两棵二叉树,原始树 original 和克隆树 cloned,以及一个位于原始树 original 中的目标节点 target。
其中,克隆树 cloned 是原始树 original 的一个 副本 。 请找出在树 cloned 中,与 target 相同的节点,并返回对该节点的引用(在 C/C++ 等有指针的语言中返回 节点指针,其他语言返回节点本身)。 注意: 你不能对两棵二叉树,以及target 节点进行更改。 只能 返回对克隆树 cloned 中已有的节点的引用。

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

输入: tree = [7,4,3,null,null,6,19], target = 3
输出: 3
解释: 上图画出了树original 和 cloned。target 节点在树 original 中,用绿色标记。
答案是树 cloned中的黄颜色的节点(其他示例类似)。
示例 2:
在这里插入图片描述

输入: tree = [7], target = 7
输出: 7
示例 3:
在这里插入图片描述

输入: tree = [8,null,6,null,5,null,4,null,3,null,2,null,1], target = 4
输出: 4
示例 4:
在这里插入图片描述

输入: tree = [1,2,3,4,5,6,7,8,9,10], target = 5
输出: 5
示例 5:
在这里插入图片描述

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

提示: 树中节点的数量范围为 [1, 10^4] 。 同一棵树中,没有值相同的节点。 target 节点是树 original
中的一个节点,并且不会是 null 。

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

思路解析:本质还是递归遍历,既然cloned 树是original树的克隆,那就需要同步遍历,只要找到(original遍历的当前结点=target结点)就返回cloned树对应的结点。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {
public:
    TreeNode* getTargetCopy(TreeNode* original, TreeNode* cloned, TreeNode* target) {
        if(original==NULL || cloned==NULL || target==NULL) return NULL;
        if(original==target) return cloned;
        TreeNode* l = getTargetCopy(original->left,cloned->left,target);
        TreeNode* r = getTargetCopy(original->right,cloned->right,target);
        return l !=NULL?l:r;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    public final TreeNode getTargetCopy(final TreeNode original, final TreeNode cloned, final TreeNode target) {
        if(original==null || cloned==null||target==null) return null;
        if(original==target) return cloned;
        TreeNode l = getTargetCopy(original.left,cloned.left,target);
        TreeNode r = getTargetCopy(original.right,cloned.right,target);
        return l==null?r:l;
    }
}

题解代码(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 getTargetCopy(self, original: TreeNode, cloned: TreeNode, target: TreeNode) -> TreeNode:
        if original is None or cloned is None or target is None:
            return None
        if original is target:
            return cloned
        l = self.getTargetCopy(original.left,cloned.left,target)
        r = self.getTargetCopy(original.right,cloned.right,target)

        return l if l is not None else r

5.2、1302. 层数最深叶子节点的和

给你一棵二叉树,请你返回层数最深的叶子节点的和。

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

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

提示:

树中节点数目在 1 到 10^4 之间。 每个节点的值在 1 到 100 之间。

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

思路解析:记得以前层次遍历【2.3、102. 二叉树的层序遍历】中,得到输出的遍历结果 [ [3], [9,20], [15,7] ] 吗?
就把输出结果最后的一个数组累加和输出即可。(本题属于回顾复习题)

也可以先求树的高度,然后再递归,深度满足的叶子结点值就可以加到累加和中。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int deepestLeavesSum(TreeNode* root) {
        int res = 0;
        if(root!=NULL){
            queue<TreeNode*> q;
            q.push(root);
            vector<vector<int>> temp;
            while(!q.empty()){
                int count = q.size();
                vector<int> v;
                while(count>0){
                    TreeNode* cur = q.front();
                    q.pop();
                    v.push_back(cur->val);
                    if(cur->left!=NULL) q.push(cur->left);
                    if(cur->right!=NULL) q.push(cur->right);
                    count--;
                }
                temp.push_back(v);
            }
            for(int i=0;i<temp[temp.size()-1].size();i++){
                res+=temp[temp.size()-1][i];
            }
        }
        return res;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int deepestLeavesSum(TreeNode root) {
        if(root==null) return 0;
        int res = 0;
        List<List<Integer>> temp = new ArrayList<List<Integer>>();
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        while(!q.isEmpty()){
            int count = q.size();
            List<Integer> v = new ArrayList<>();
            while(count>0){
                TreeNode t = q.poll();
                v.add(t.val);
                if(t.left!=null) q.offer(t.left);
                if(t.right!=null) q.offer(t.right);
                count--;
            }
            temp.add(v);
        }
        int last = temp.size()-1;
        for(int a :temp.get(last))
            res+=a;
        return res;
    }
}

题解代码(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 deepestLeavesSum(self, root: TreeNode) -> int:
        if root is None:
            return 0
        q = []
        temp = []
        q.append(root)
        while len(q)>0:
            count = len(q)
            v = []
            while count>0 :
                cur = q.pop(0)
                v.append(cur.val)
                if cur.left is not None:
                    q.append(cur.left)
                if cur.right is not None:
                    q.append(cur.right)
                count-=1
            temp.append(v)
        
        return sum(temp[-1])

5.3、654. 最大二叉树

给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:

二叉树的根是数组中的最大元素。
左子树是通过数组中最大值左边部分构造出的最大二叉树。
右子树是通过数组中最大值右边部分构造出的最大二叉树。
通过给定的数组构建最大二叉树,并且输出这个树的根节点。
示例 :
输入:[3,2,1,6,0,5] 输出:返回下面这棵树的根节点:

   6
 /    \    
3      5
 \     / 
  2   0   
   \
    1  

提示:

给定的数组的大小在 [1, 1000] 之间。

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

思路解析:可以递归构造树,首先要找到数组中最大值,然后记录索引mid,根据最大值创建结点,结点左右子树根据索引切片得到的数组来构造。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* constructMaximumBinaryTreeHelper(vector<int>& nums,int l,int r){
        if(l>r) return NULL;
        int max = INT_MIN;
        int mid = 0;
        for(int i=l;i<=r;i++){
            if(nums[i]>max) {
                max = nums[i];
                mid = i;
            }
        }
        TreeNode* root = new TreeNode(nums[mid]);
        root->left = constructMaximumBinaryTreeHelper(nums,l,mid-1);
        root->right = constructMaximumBinaryTreeHelper(nums,mid+1,r);
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        if(nums.size()!=0){
            TreeNode* res = constructMaximumBinaryTreeHelper(nums,0,nums.size()-1);
            return res;
        }else{
            return NULL;
        }
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode constructMaximumBinaryTreeHelper(int[] nums,int l,int r){
        if(l>r) return null;
        int max = Integer.MIN_VALUE;
        int mid = 0;
        for(int i=l;i<=r;i++){
            if(max<nums[i]) {
                max = nums[i];
                mid = i;
            }
        }
        TreeNode root = new TreeNode(nums[mid]);
        root.left = constructMaximumBinaryTreeHelper(nums,l,mid-1);
        root.right = constructMaximumBinaryTreeHelper(nums,mid+1,r);
        return root;
    }
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        if(nums.length==0) return null;
        else return constructMaximumBinaryTreeHelper(nums,0,nums.length-1);
    }
}

题解代码(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 constructMaximumBinaryTreeHelper(self,nums:List[int],l:int,r:int) ->TreeNode:
        if l>r:
            return None
        MaxNum = -pow(2,32)
        mid = 0
        for i in range(l,r+1):
            if MaxNum<nums[i]:
                MaxNum = nums[i]
                mid = i
        root = TreeNode(nums[mid])
        root.left = self.constructMaximumBinaryTreeHelper(nums,l,mid-1)
        root.right = self.constructMaximumBinaryTreeHelper(nums,mid+1,r)
        return root

    def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode:
        if len(nums)==0:
            return None
        else:
            return self.constructMaximumBinaryTreeHelper(nums,0,len(nums)-1)

5.4、1315. 祖父节点值为偶数的节点和

给你一棵二叉树,请你返回满足以下条件的所有节点的值之和:该节点的祖父节点的值为偶数。
(一个节点的祖父节点是指该节点的父节点的父节点。) 如果不存在祖父节点值为偶数的节点,那么返回 0 。
示例:在这里插入图片描述

输入:root = [6,7,8,2,7,1,3,9,null,1,4,null,null,null,5]
输出:18
解释:图中红色节点的祖父节点的值为偶数,蓝色节点为这些红色节点的祖父节点。

提示:
树中节点的数目在 1 到 10^4 之间。
每个节点的值在 1 到 100 之间。

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

思路解析:遍历一遍所有的结点,如果当前结点的值是偶数,就看有没有孙子结点,如果有就加入到累加和,最后返回即可。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int res = 0;
    void dfs(TreeNode* root){
        if(root==NULL) return;
        if(root->val%2==0){
            if(root->left!=NULL){
                if(root->left->left!=NULL) this->res+=root->left->left->val;
                if(root->left->right!=NULL) this->res+=root->left->right->val;
            } 
            if(root->right!=NULL){
                if(root->right->left!=NULL) this->res+=root->right->left->val;
                if(root->right->right!=NULL) this->res+=root->right->right->val;
            } 
        }
        dfs(root->left);
        dfs(root->right);
    }

    int sumEvenGrandparent(TreeNode* root) {
        if(root==NULL) return 0;
        this->res = 0;
        dfs(root);
        return this->res;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int res;

    public void dfs(TreeNode root){
        if(root==null) return;
        if(root.val%2==0){
            if(root.left!=null){
                if(root.left.left!=null) this.res+=root.left.left.val;
                if(root.left.right!=null) this.res+=root.left.right.val;
            }
            if(root.right!=null){
                if(root.right.left!=null) this.res+=root.right.left.val;
                if(root.right.right!=null) this.res+=root.right.right.val;
            }
        }
        dfs(root.left);
        dfs(root.right);
    }

    public int sumEvenGrandparent(TreeNode root) {
        if(root==null) return 0;
        this.res =0;
        dfs(root);
        return this.res;
    }
}

题解代码(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 __init__(self):
        self.res = 0

    def dfs(self,root:TreeNode):
        if root is None:
            return None

        if root.val % 2 == 0:
            if root.left is not None:
                if root.left.left is not None:
                    self.res +=root.left.left.val
                if root.left.right is not None:
                    self.res+= root.left.right.val
            if root.right is not None:
                if root.right.left is not None:
                    self.res +=root.right.left.val
                if root.right.right is not None:
                    self.res+= root.right.right.val

        self.dfs(root.left)
        self.dfs(root.right)

    def sumEvenGrandparent(self, root: TreeNode) -> int:
        if root is None:
            return 0
        self.res = 0
        self.dfs(root)
        return self.res

5.5、701. 二叉搜索树中的插入操作

给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 保证原始二叉搜索树中不存在新值。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回任意有效的结果。

例如,

给定二叉搜索树:

    4
   / \
  2   7
 / \
1   3

和 插入的值: 5 你可以返回这个二叉搜索树:

     4
   /   \
  2     7
 / \   /
1   3 5 
或者这个树也是有效的:

     5
   /   \
  2     7
 / \   
1   3
     \
      4

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

思路解析:根据二叉搜索树的特性,查找到要插入的位置,顺势插入即可。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void searchBST(TreeNode* root,int &val){
        if(root==NULL) return;  
        if(root->val>val){
            if(root->left==NULL) {root->left = new TreeNode(val);return;}
            else searchBST(root->left,val);
        }else{
            if(root->right==NULL) {root->right = new TreeNode(val);return;}
            else searchBST(root->right,val);
        }
    }
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root==NULL) return NULL;
        searchBST(root,val);
        return root;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public void searchBST(TreeNode root,int val){
        if(root==null) return;
        if(root.val>val){
            if(root.left==null){root.left=new TreeNode(val); return;}
            else searchBST(root.left,val);
        }else{
            if(root.right==null){root.right=new TreeNode(val); return;}
            else searchBST(root.right,val);
        }
    }
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if(root==null) return null;
        searchBST(root,val);
        return root;
    }
}

题解代码(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 search(self,root:TreeNode,val:int):
        if root is None:
            return None
        if root.val>val:
            if root.left is None:
                root.left = TreeNode(val)
            else:
                self.search(root.left,val)
        else:
            if root.right is None:
                root.right = TreeNode(val)
            else:
                self.search(root.right,val)

    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
        if root is None:
            return None
        self.search(root,val)
        return root

5.6、894. 所有可能的满二叉树

满二叉树是一类二叉树,其中每个结点恰好有 0 或 2 个子结点。

返回包含 N 个结点的所有可能满二叉树的列表。 答案的每个元素都是一个可能树的根结点。

答案中每个树的每个结点都必须有 node.val=0。

你可以按任何顺序返回树的最终列表。
示例:

输入:7
输出:[[0,0,0,null,null,0,0,null,null,0,0],[0,0,0,null,null,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,null,null,null,null,0,0],[0,0,0,0,0,null,null,0,0]]
解释:
在这里插入图片描述

提示:

1 <= N <= 20

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

思路解析:有点难度,有点挑战。首先要确定一下N的取值范围,如果N<1,则构不成树,如果N是偶数,就不满足 每个结点恰好有 0 或 2 个子结点这个条件。因为每个结点0或2个子结点,那么这种树的分支树一定为偶数,而N为偶数的时候,构成的树分支树却是奇数,所以N不能为偶数。

接下来还需要分析给出N(奇数),可以构建多少棵满足条件的树?
例如:N=7,先构建一个根节点,则剩下6个结点,可以分配给左右孩子结点数的方案有:(1,5)、(3,3)、(5,1),那么就是至少可以构建3棵,如果N=5,分配方案有:(1,3),(3,1),至少可以构建2棵,如果N=3,分配方案只有(1,1),只能构建一棵树,如果N=1,只有一个结点的树。
根据上面分析,N=7应该是可以构建5棵树,N=5是可以构建2棵树,N=1或N=3都只能构建一棵树。

总结:
假设:vector<TreeNode*> allPossibleFBT(int N)
1、根据分配的方案不同,需要一个遍历:
for(int i=1;i<=N-2;i+=2) (i、N-1-i)表示一种分配方案
2、左边可选的子树:allPossibleFBT(i) 返回的树的vector
右边可选的子树:allPossibleFBT(N-1-i) 返回的树的vector
3、取2中的两个vector的组合作为新创结点的左右孩子,最后把新创的结点加入到res结果中去,最后循环完毕返回即可。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<TreeNode*> allPossibleFBT(int N) {
        vector<TreeNode*> res;
        if(N % 2 == 0) return res;
        if(N == 1) {res.push_back(new TreeNode(0));return res;}
        for(int i=1;i<=N-2;i+=2){
            vector<TreeNode*> left = allPossibleFBT(i);
            vector<TreeNode*> right = allPossibleFBT(N-1-i);
            for(int j=0;j<left.size();++j){
                for(int k=0;k<right.size();++k){
                    TreeNode *root = new TreeNode(0);
                    root->left = left[j];
                    root->right = right[k];
                    res.push_back(root);
                }
            }
        }
        return res;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<TreeNode> allPossibleFBT(int N) {
        List<TreeNode> res = new ArrayList<TreeNode>();
        if(N%2==0) return res;
        if(N==1){
            res.add(new TreeNode(0));
            return res;
        }
        for(int i=1;i<=N-2;i+=2){
            List<TreeNode> left = allPossibleFBT(i);
            List<TreeNode> right = allPossibleFBT(N-i-1);
            for(TreeNode l:left){
                for(TreeNode r:right){
                    TreeNode root = new TreeNode(0);
                    root.left = l;
                    root.right = r;
                    res.add(root);
                }
            }
        }
        return res;
    }
}

题解代码(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 allPossibleFBT(self, N: int) -> List[TreeNode]:
        res = []
        if N%2 ==0:
            return res
        if N==1:
            res.append(TreeNode(0))
            return res
        for i in range(1,N,2):
            lefts = self.allPossibleFBT(i)
            rights = self.allPossibleFBT(N-i-1)
            for l in lefts:
                for r in rights:
                    root = TreeNode(0)
                    root.left = l
                    root.right = r
                    res.append(root)

        return res

5.7、1305. 两棵二叉搜索树中的所有元素

给你 root1 和 root2 这两棵二叉搜索树。

请你返回一个列表,其中包含 两棵树 中的所有整数并按 升序 排序。.

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

输入:root1 = [2,1,4], root2 = [1,0,3] 输出:[0,1,1,2,3,4]
示例 2:

输入:root1 = [0,-10,10], root2 = [5,1,7,0,2] 输出:[-10,0,0,1,2,5,7,10]
示例 3:

输入:root1 = [], root2 = [5,1,7,0,2] 输出:[0,1,2,5,7]
示例 4:

输入:root1 = [0,-10,10], root2 = [] 输出:[-10,0,10]
示例 5:
在这里插入图片描述

输入:root1 = [1,null,8], root2 = [8,1] 输出:[1,1,8,8]

提示:

每棵树最多有 5000 个节点。 每个节点的值在 [-10^5, 10^5] 之间。

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

思路解析:两棵二叉搜索树分别中序遍历,然后得到两个升序的数组,最终合并到一个数组即可,思路清晰明了。
时间复杂度:O(M+N) 遍历一遍树和遍历一遍数组即可
空间复杂度:O(M+N) 额外的数组来存放遍历输出结果

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void dfs(TreeNode* root,vector<int> &res){
        if(root==NULL) return;
        dfs(root->left,res);
        res.push_back(root->val);
        dfs(root->right,res);
    }

    vector<int> getAllElements(TreeNode* root1, TreeNode* root2) {
        vector<int> v1;
        vector<int> v2;
        dfs(root1,v1);
        dfs(root2,v2);
        vector<int> res;
        int i=0,j=0;
        while(i<v1.size() || j<v2.size()){
            if(i<v1.size()&&(j==v2.size()||v1[i]<v2[j])){
                res.push_back(v1[i++]);
            }else{
                res.push_back(v2[j++]);
            }
        }
        return res;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public void dfs(TreeNode root,List<Integer> res){
        if(root==null) return;
        dfs(root.left,res);
        res.add(root.val);
        dfs(root.right,res);
    }
    public List<Integer> getAllElements(TreeNode root1, TreeNode root2) {
        List<Integer> v1 = new ArrayList<Integer>();
        List<Integer> v2 = new ArrayList<Integer>();
        List<Integer> res = new ArrayList<Integer>();
        dfs(root1,v1);
        dfs(root2,v2);
        int i=0,j=0;
        while(i<v1.size()||j<v2.size()){
            if(i<v1.size()&&(j==v2.size()||v1.get(i)<v2.get(j))){
                res.add(v1.get(i));
                i++;
            }else{
                res.add(v2.get(j));
                j++;
            }
        }
        return res;
    }
}

题解代码(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 dfs(self,root:TreeNode,res:List[int]):
        if root is None:
            return None
        self.dfs(root.left,res)
        res.append(root.val)
        self.dfs(root.right,res)

    def getAllElements(self, root1: TreeNode, root2: TreeNode) -> List[int]:
        v1,v2 = [],[]
        self.dfs(root1,v1)
        self.dfs(root2,v2)
        res = []
        i,j = 0,0
        while i<len(v1) or j <len(v2):
            if i<len(v1) and (j==len(v2) or v1[i]<v2[j]):
                res.append(v1[i])
                i+=1
            else:
                res.append(v2[j])
                j+=1
        return res

5.8、814. 二叉树剪枝

给定二叉树根结点 root ,此外树的每个结点的值要么是 0,要么是 1。

返回移除了所有不包含 1 的子树的原二叉树。

( 节点 X 的子树为 X 本身,以及所有 X 的后代。)

示例1: 输入: [1,null,0,0,1] 输出: [1,null,0,null,1] 解释: 只有红色节点满足条件“所有不包含
1 的子树”。 右图为返回的答案。
在这里插入图片描述

示例2: 输入: [1,0,1,0,0,0,1] 输出: [1,null,1,null,1]

在这里插入图片描述

示例3: 输入: [1,1,0,1,1,0,1,0] 输出: [1,1,0,1,1,null,1]
在这里插入图片描述

说明:

给定的二叉树最多有 100 个节点。 每个节点的值只会为 0 或 1 。

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

思路解析:本题使用递归来剪枝,试想一棵树,如果root为NULL,则返回false,表示所给的树没有含有1 的结点。
当root不为空的时候:
如果它的左子树没有含有1的结点,则令左孩子为NULL,同理右子树没有含有1的结点,则令右孩子为NULL。
在裁剪了左右子树之后,如果只剩下root一个根节点,即左右孩子均为NULL,表示左右子树都没有含有1的结点,那么就再判断根节点root的值,如果root->val为1,则返回true,表示root这棵树有1的结点,如果root->val为0,则返回fasle,表示root这棵树没有1的结点。
其他的情况就返回true,因为剪枝后的root树还有左右孩子的话,就表示这root树含有1 的结点。

简单框架:

bool dfs(TreeNode* root){
    if(root==NULL) return false;
	if(!dfs(root->left)){
		root->left = NULL;
	}
	if(!dfs(root->right)){
		root->right=NULL;
	}
	if(root->left==NULL && root->right==NULL && root->val==0) return false;
	else return true;
}

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool dfs(TreeNode* root){
        if(root==NULL) return false;
        bool l = dfs(root->left);
        bool r = dfs(root->right);
        if(!l){
            root->left=NULL;
        }
        if(!r){
            root->right=NULL;
        }
        if(root->right==NULL && root->left==NULL && root->val==0) return false;
        else return true;
    }
    TreeNode* pruneTree(TreeNode* root) {
        if(root==NULL) return NULL;
        if(dfs(root)) return root;
        else return NULL;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    boolean dfs(TreeNode root){
        if(root==null) return false;
        if(!dfs(root.left)) root.left=null;
        if(!dfs(root.right)) root.right=null;
        if(root.left==null && root.right==null && root.val==0) return false;
        else return true;
    }
    public TreeNode pruneTree(TreeNode root) {
        if(root==null) return null;
        if(dfs(root)) return root;
        else return null;
    }
}

题解代码(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 dfs(self,root:TreeNode)->bool:
        if root is None:
            return False
        if not self.dfs(root.left):
            root.left = None
        if not self.dfs(root.right):
            root.right = None
        if root.left is None and root.right is None and root.val ==0:
            return False
        else:
            return True

    def pruneTree(self, root: TreeNode) -> TreeNode:
        if root is None:
            return None
        if self.dfs(root):
            return root
        else:
            return None

5.9、173. 二叉搜索树迭代器

实现一个二叉搜索树迭代器。你将使用二叉搜索树的根节点初始化迭代器。

调用 next() 将返回二叉搜索树中的下一个最小的数。
示例: 在这里插入图片描述

BSTIterator iterator = new BSTIterator(root); iterator.next(); //
返回 3 iterator.next(); // 返回 7 iterator.hasNext(); // 返回 true
iterator.next(); // 返回 9 iterator.hasNext(); // 返回 true
iterator.next(); // 返回 15 iterator.hasNext(); // 返回 true
iterator.next(); // 返回 20 iterator.hasNext(); // 返回 false

提示:
next() 和 hasNext() 操作的时间复杂度是 O(1),并使用 O(h) 内存,其中 h 是树的高度。
你可以假设 next()调用总是有效的,也就是说,当调用 next() 时,BST 中至少存在一个下一个最小的数。

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

思路解析:本题是一个设计类的题,使用的是二叉搜索树的结构,调用next()函数来返回下一个最小的值,调用hasNext()来判断是否还有值。

并且题目说了,next() 和 hasNext() 操作的时间复杂度是 O(1),并使用 O(h) 内存。
也就是说,先遍历一遍把所有结果放到一个数组里,然后迭代输出,这种方法虽然简便,但是违反了设计理念,这就退化成输出一个数组了。
一个迭代器对象最主要的一点就是所需的空间要小,而且取数据操作时间复杂度为O(1)。
在二叉树的遍历中,之前使用的都是递归的方法,下面简单介绍一下非递归的方法,本题就靠这个非递归的方法了。

首先,递归的调用隐式地使用了栈的数据结构,既然要用非递归实现,那么一个栈是必不可少的,而且在遍历过程中,栈所需的空间最多达到h(树高)。

在这里插入图片描述
1、根据中序遍历,首先是要找到第一个访问的结点,第一个访问的结点是什么样的结点呢?一定是根节点root的左孩子的左孩子的…的左孩子,直到某个结点的左孩子为空,期间一直在压栈。(可以回顾中序遍历递归的代码)
2、如上图所示:不断迭代找到第一访问的结点,并且期间不断压栈。
3、当出现了某个结点左孩子为空的时候,说明已经找到要访问的结点了,就被压在栈顶,只需要取出来然后访问即可。
4、访问完某个结点后,然后就是看它的右孩子,如果不为空依然是压栈,继续找到左孩子为空的结点。
5、如果在第4步发现右孩子为空,那么就访问栈顶元素吧,栈顶元素一定是父节点,因为按次序压栈的嘛。(语言叙述不是很给力,建议自己画图推导推导)
6、如果把栈的元素清空了,那么就相当于递归完毕,那就是遍历结束。

非递归中序遍历二叉树的框架:

void inorder(TreeNode* root,vector<int> &res){
        stack<TreeNode*> s;
        TreeNode* cur = root;
        while(cur!=NULL ||!s.empty()){
            while(cur!=NULL){
                s.push(cur);
                cur = cur->left;
            }
            if(!s.empty()){
                cur = s.top();s.pop();
                res.push_back(cur->val);
                cur = cur->right;
            }
        }
    }

本题借助非递归中序遍历二叉树来解决问题。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class BSTIterator { 
public:
    stack<TreeNode*> s;
    BSTIterator(TreeNode* root) {
        //先迭代找到第一个要访问的结点
        while(root){
            s.push(root);
            root = root->left;
        }
    }
    
    /** @return the next smallest number */
    int next() {
        TreeNode* temp = s.top();s.pop();
        int res = temp->val;
        temp = temp->right;
        while(temp){
            s.push(temp);
            temp = temp->left;
        }
        return res;
    }
    
    /** @return whether we have a next smallest number */
    bool hasNext() {
        return !s.empty();
    }
};

/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator* obj = new BSTIterator(root);
 * int param_1 = obj->next();
 * bool param_2 = obj->hasNext();
 */

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class BSTIterator {
    Stack<TreeNode> s = new Stack<>();
    public BSTIterator(TreeNode root) {
        while(root!=null){
            this.s.push(root);
            root = root.left;
        }
    }
    
    /** @return the next smallest number */
    public int next() {
        TreeNode temp = this.s.pop();
        int res = temp.val;
        temp = temp.right;
        while(temp!=null){
            this.s.push(temp);
            temp = temp.left;
        }
        return res;
    }
    
    /** @return whether we have a next smallest number */
    public boolean hasNext() {
        return this.s.size()>0;
    }
}

/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator obj = new BSTIterator(root);
 * int param_1 = obj.next();
 * boolean param_2 = obj.hasNext();
 */

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class BSTIterator:

    def __init__(self, root: TreeNode):
        self.s = []
        while root:
            self.s.append(root)
            root = root.left

    def next(self) -> int:
        """
        @return the next smallest number
        """
        temp = self.s.pop()
        res = temp.val
        temp = temp.right
        while temp is not None:
            self.s.append(temp)
            temp = temp.left
        return res

    def hasNext(self) -> bool:
        """
        @return whether we have a next smallest number
        """
        return len(self.s)>0


# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()

5.10、1008. 先序遍历构造二叉树

返回与给定先序遍历 preorder 相匹配的二叉搜索树(binary search tree)的根结点。

(回想一下,二叉搜索树是二叉树的一种,其每个节点都满足以下规则,对于 node.left 的任何后代,值总 < node.val,而node.right 的任何后代,值总 node.val。此外,先序遍历首先显示节点的值,然后遍历 node.left,接着遍历 node.right。)

示例:

输入:[8,5,1,7,10,12] 输出:[8,5,10,1,7,null,12]
在这里插入图片描述

提示:

1 <= preorder.length <= 100 先序 preorder 中的值是不同的。

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

思路解析:注意要看题目:返回与给定先序遍历 preorder 相匹配的二叉搜索树。
如果光是有先序遍历的preorder,而没有二叉搜索树的限制,最简单的就是不断加左孩子结点或者是右孩子结点,都退化成链表了。
言归正传,既然是二叉搜索树,其中序遍历的结果是一个升序的数组,学过数据结构的都知道,知道先序遍历和中序遍历的结果,就可以确定唯一一棵二叉树。
所以本题隐式地提醒我们,要排序,得到中序遍历结果,然后根据先序中序遍历结果构建树。

也可以不用排序,思路2:
先序遍历的第一个元素肯定是根节点,然后要根据二叉搜索树的特性,比根节点小的在左子树,比根节点大的在右子树,需要把先序遍历的元素分为两部分,然后可以递归构造树了。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* bstFromPreorderHelper(vector<int>& preorder,int l,int r){
        if(l>r) return NULL;
        TreeNode* root = new TreeNode(preorder[l]);
        int index = l+1;
        for(;index<=r;index++) if(preorder[l]<preorder[index]) break;
        root->left = bstFromPreorderHelper(preorder,l+1,index-1);
        root->right = bstFromPreorderHelper(preorder,index,r);
        return root;
    }
    TreeNode* bstFromPreorder(vector<int>& preorder) {
        if(preorder.size()==0) return NULL;
        else return bstFromPreorderHelper(preorder,0,preorder.size()-1);
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode bstFromPreorderHelper(int[] preorder,int l,int r){
        if(l>r) return null;
        TreeNode root = new TreeNode(preorder[l]);
        int index = l+1;
        for(;index<=r;index++) if(preorder[l]<preorder[index]) break;
        root.left = bstFromPreorderHelper(preorder,l+1,index-1);
        root.right = bstFromPreorderHelper(preorder,index,r);
        return root;
    }
    public TreeNode bstFromPreorder(int[] preorder) {
        if(preorder.length==0) return null;
        else return bstFromPreorderHelper(preorder,0,preorder.length-1);
    }
}

题解代码(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 bstFromPreorderHelper(self,preorder:List[int],l:int,r:int) ->TreeNode:
        if l>r:
            return None
        root = TreeNode(preorder[l])
        index = l+1
        while index<=r:
            if preorder[l]<preorder[index]:
                break;
            index+=1
        root.left = self.bstFromPreorderHelper(preorder,l+1,index-1)
        root.right = self.bstFromPreorderHelper(preorder,index,r)
        return root
    def bstFromPreorder(self, preorder: List[int]) -> TreeNode:
        if len(preorder) ==0 :
            return None
        else:
            return self.bstFromPreorderHelper(preorder,0,len(preorder)-1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值