美文网首页
LeetCode—— 合并二叉树

LeetCode—— 合并二叉树

作者: Minority | 来源:发表于2020-02-09 17:14 被阅读0次

    题目描述

    给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
    
    你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
    
    示例 1:
    
    输入: 
        Tree 1                     Tree 2                  
              1                         2                             
             / \                       / \                            
            3   2                     1   3                        
           /                           \   \                      
          5                             4   7                  
    输出: 
    合并后的树:
             3
            / \
           4   5
          / \   \ 
         5   4   7
    注意: 合并必须从两个树的根节点开始。
    
    一、CPP
    1. 递归法:

    解题思路:对这两棵树同时进行前序遍历,并将r1和r2对应的节点进行合并到r1上。在遍历时,如果两棵树的当前节点均不为空,我们就将它们的值进行相加,并对它们的左孩子和右孩子进行递归合并;如果其中有一棵树为空,那么我们返回另一颗树作为结果;如果两棵树均为空,此时返回任意一棵树均可(因为都是空)。
    时间复杂度:O(N),其中 N是两棵树中节点个数的较小值。
    空间复杂度:O(N),在最坏情况下,会递归 N 层,需要O(N) 的栈空间。

    /**
     * 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* mergeTrees(TreeNode* t1, TreeNode* t2) {
    
            //前序遍历:根左右
            if(t1 == NULL || t2== NULL){
                return t1 == NULL ? t2 : t1;
            }
            
            t1->val = t1->val + t2->val;
            t1->left = mergeTrees(t1->left,t2->left);
            t1->right = mergeTrees(t1->right,t2->right);
    
            return t1;
    
            
        }
    };
    
    • 注意:C++指针类型的结构体需要使用“->”,而不能使用“.”。
    2. 迭代法(层次遍历一):

    解题思路:迭代实现用的是广度优先算法,广度优先就需要额外的数据结构来辅助了,可以借助栈或者队列来完成。下面使用队列来完成。只要两颗树的左节点都不为null,就把将他们放入队列中;同理只要两棵树的右节点都不为null了,也将他们放入队列中。然后我们不断的从队列中取出节点,把他们相加。如果出现 树1的left节点为null,树2的left不为null,直接将树2的left赋给树1就可以了;同理如果树1的right节点为null,树2的不为null,将树2的right节点赋给树1。
    时间复杂度:O(N),其中 N是两棵树中节点个数的较小值。
    空间复杂度:O(N),最坏的情况,对于满二叉树时,要保存所有的叶子节点,即N/2个节点

    /**
     * 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* mergeTrees(TreeNode* t1, TreeNode* t2) {
    
            if(t1 == NULL || t2 == NULL){
                return t1 == NULL ? t2 : t1;
            }
    
            queue<TreeNode*> myqueue;
            myqueue.push(t1);
            myqueue.push(t2);
    
            //注意是TreeNode的指针类型,在node1基础上进行修改
            TreeNode *node1,*node2;
            while(!myqueue.empty()){
    
                //顺序遍历:根
                node1 = myqueue.front();
                myqueue.pop();
                node2 = myqueue.front();
                myqueue.pop();
                node1->val = node1->val + node2->val;
                
                //左子树
                if(node1->left && node2->left){
                    myqueue.push(node1->left);
                    myqueue.push(node2->left);
                }
                else if(node1->left == NULL){
                    node1->left = node2->left;
                }
    
                //右子树
                if(node1->right && node2->right){
                    myqueue.push(node1->right);
                    myqueue.push(node2->right);
                }
                else if(node1->right == NULL){
                    node1->right = node2->right;
                }
    
            }
    
            return t1;
        }
    };
    
    3. 迭代法(层次遍历二):

    解题思路:每次从两个树中各取一个节点(记为node1, node2)入队;出队时将两个节点值相加,并判断node1和node2的左子树是否为空,若两个左子树都不空,直接入队;若有一个为空,新建一个val为0的节点,然后入队;若两个的左子树都为空,pass。右子树的判断同理。
    时间复杂度:O(N),其中 N是两棵树中节点个数的较小值。
    空间复杂度:O(N)。运行超出了内存限制

    /**
     * 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* mergeTrees(TreeNode* t1, TreeNode* t2) {
    
            if(t1 == NULL || t2 == NULL){
                return t1 == NULL ? t2 : t1;
            }
    
            queue<TreeNode*> myqueue;
            TreeNode *node1, *node2;
    
            myqueue.push(t1);
            myqueue.push(t2);
    
            while(!myqueue.empty()){
    
                //层序遍历
                node1 = myqueue.front();
                myqueue.pop();
                node2 = myqueue.front();
                myqueue.pop();
                //对应相加,遇NULL补0
                node1->val += node2->val;
    
                //左节点
                if(node1->left == NULL){
                    node1->left = new TreeNode(0);
                }
                if(node2->left == NULL){
                    node2->left = new TreeNode(0);
                }
                myqueue.push(node1->left);
                myqueue.push(node2->left);
    
                //右节点
                if(node1->right == NULL){
                    node1->right = new TreeNode(0);
                }
                if(node2->right == NULL){
                    node2->right = new TreeNode(0);
                }
                myqueue.push(node1->right);
                myqueue.push(node2->right);
            }
            
            return t1;
        }
    };
    

    同样的方法和思路,用下面这种方式写就没事......不解。

    class Solution {
    public:
        TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2)
        {
            if(!t1)
                return t2;
            if(!t2)
                return t1;
    
            queue<TreeNode*> q;
            q.push(t1);
            q.push(t2);
            TreeNode *node1, *node2;
    
            while(!q.empty()){
                node1 = q.front();
                q.pop();
                node2 = q.front();
                q.pop();
    
                node1->val += node2->val;  //val相加
    
                if(node1->left || node2->left){ //左子树判断
                    if(!node1->left)
                        node1->left = new TreeNode(0);
                    if(!node2->left)
                        node2->left = new TreeNode(0);
                    q.push(node1->left);
                    q.push(node2->left);
                }
                if(node1->right || node2->right){   //右子树判断
                    if(!node1->right)
                        node1->right = new TreeNode(0);
                    if(!node2->right)
                        node2->right = new TreeNode(0);
                    q.push(node1->right);
                    q.push(node2->right);
                }
            }
            return t1;
        }
    };
    
    二、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 mergeTrees(TreeNode t1, TreeNode t2) {
            
            //java中的null是小写
            if(t1 == null || t2 == null){
                return t1 == null ? t2 : t1;
            }
    
            t1.val += t2.val;
            t1.left = mergeTrees(t1.left,t2.left);
            t1.right = mergeTrees(t1.right,t2.right);
    
            return t1;
            
        }
    }
    
    三、Python(递归法)
    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution(object):
        def mergeTrees(self, t1, t2):
            """
            :type t1: TreeNode
            :type t2: TreeNode
            :rtype: TreeNode
            """
            if t1 is None or t2 is None:
                if t1:
                    return t1
                else:
                    return t2
            t1.val += t2.val
            t1.left = self.mergeTrees(t1.left,t2.left)
            t1.right = self.mergeTrees(t1.right,t2.right)
    
            return t1;
    
    四、各语言及算法时间复杂度

    相关文章

      网友评论

          本文标题:LeetCode—— 合并二叉树

          本文链接:https://www.haomeiwen.com/subject/kqvgxhtx.html