• leetcode每天5题-Day42


    1.翻转二叉树

    226. 翻转二叉树-简单
    b站-代码随想录
    递归
    递归三部曲:

    1. 确定递归函数的参数和返回值
    2. 确定终止条件
    3. 确定单层递归的逻辑

    “使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!”

    前序👇

    var invertTree = function(root) {
        if(root === null) return root;
        [[root.left], [root.right]] = [[root.right], [root.left]]
        invertTree(root.left);
        invertTree(root.right);
        return root;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    另一个版本👇

    var invertTree = function(root) {
        // 终止条件
        if (!root) {
            return null;
        }
        // 交换左右节点
        const rightNode = root.right;  // 要先把右节点存起来
        root.right = invertTree(root.left);
        root.left = invertTree(rightNode);
        return root;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    后序👇

    var invertTree = function(root) {
        if(root === null) return root;
        invertTree(root.left);
        invertTree(root.right);
        [[root.left], [root.right]] = [[root.right], [root.left]]
        return root;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    中序👇

    左子树翻转后,根节点翻转,翻转后的右子树是之前已经翻转过的左子树,而左子树是之前还未进行翻转的右子树。

    var invertTree = function(root) {
        if(root === null) return root;
        invertTree(root.left);
        [[root.left], [root.right]] = [[root.right], [root.left]]
        invertTree(root.left);
        return root;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    迭代(利用栈)

    var invertTree = function(root) {
        //  定义翻转左右节点的函数
        var swapNode = function(root,left,right) {
            let temp = left;
            left = right;
            right = temp;
            root.left = left;
            root.right = right;
        }
    
            // 迭代  前序遍历  根左右
            const stack = [];
            if(!root) return root;
            stack.push(root);
            while(stack.length) {
                let node = stack.pop();
                if(node) {
                    //  入栈顺序 右左根
                    node.right && stack.push(node.right);
                    node.left && stack.push(node.left);
                    stack.push(node);
                    //  从根节点开始 按照根左右的顺序翻转
                    // 空节点做标记
                    stack.push(null);
                }else{
                    node = stack.pop();
                    swapNode(node, node.left, node.right);
                }
            }
            return root;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    层序遍历(利用队列)

    var invertTree = function(root) {
        //  定义翻转左右节点的函数
        var swapNode = function(root,left,right) {
            let temp = left;
            left = right;
            right = temp;
            root.left = left;
            root.right = right;
        }
    
            // 层序遍历
            const queue = [];
            if(!root) return root;
            queue.push(root);
            while(queue.length) {
                let size = queue.length;
                while(size--){
                    let node = queue.shift();
                    swapNode(node, node.left, node.right);
                    node.left && queue.push(node.left);
                    node.right && queue.push(node.right);
                }
            }
            return root;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.N 叉树的前序遍历

    589. N 叉树的前序遍历-简单

    var preorder = function(root) {
            const ans = [];
            var pre = function(root){
                if(!root) return root;
                ans.push(root.val);
                for(let i of root.children){
                //  不要重复遍历 节点 
                    pre(i);
            }
            }
        pre(root);
        return ans;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.N 叉树的后序遍历

    590. N 叉树的后序遍历-简单

    var postorder = function(root) {
        const ans = [];
        var post = function(root) {
            if(!root) return root;
            for(let i of root.children) {
                post(i);
            }
            ans.push(root.val);
        }
        post(root);
        return ans;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.对称二叉树

    101. 对称二叉树-简单
    b站-代码随想录

    var isSymmetric = function(root) {
        if(!root.left || !root.right) {
            return root.left === root.right;
        };
        var symmetric = function(l, r) {
            if(!l && !r) {
                return true;
            }else if(l && !r){
                return false;
            }else if(r && !l){
                return false;
            }else if(l.val === r.val){
                return symmetric(l.right, r.left) && symmetric(l.left, r.right);
            }else{
                return false;
            }
        }
        return symmetric(root.left, root.right);
        
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    递归

    本题只能后序遍历(不是严格的后序遍历)

    var isSymmetric = function(root) {
        //使用递归遍历左右子树 递归三部曲
        // 1. 确定递归的参数 root.left root.right和返回值true false 
        const compareNode=function(left, right){
            //2. 确定终止条件 空的情况
            if(left===null && right!==null || left !== null && right === null){
                return false;
            }else if(left === null && right === null){
                return true;
            }else if(left.val !== right.val){
                return false;
            }
            //3. 确定单层递归逻辑
            let outSide=compareNode(left.left, right.right);
            let inSide=compareNode(left.right, right.left);
            return outSide&&inSide;
        }
        if(root === null){
            return true;
        }
        return compareNode(root.left, root.right);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    迭代

    不是层序遍历。通过一个容器(队列或栈)来成对的存放我们要比较的元素。

    队列👇

    var isSymmetric = function(root) {
      //迭代方法判断是否是对称二叉树
      //首先判断root是否为空
      if(!root){
          return true;
      }
      let queue=[];
      queue.push(root.left);
      queue.push(root.right);
      while(queue.length){
          let leftNode = queue.shift(); //左节点
          let rightNode = queue.shift(); //右节点
          if(leftNode === null && rightNode === null){
              continue;
          }
          if(leftNode === null || rightNode === null || leftNode.val !== rightNode.val){
              return false;
          }
          queue.push(leftNode.left);  //左节点左孩子入队
          queue.push(rightNode.right);  //右节点右孩子入队
          queue.push(leftNode.right);  //左节点右孩子入队
          queue.push(rightNode.left);  //右节点左孩子入队
      }
      return true;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    栈👇

    var isSymmetric = function(root) {
      //迭代方法判断是否是对称二叉树
      //首先判断root是否为空
      if(!root){
          return true;
      }
      let stack=[];
      stack.push(root.left);
      stack.push(root.right);
      while(stack.length){
          let rightNode=stack.pop();  // 右节点
          let leftNode=stack.pop();  // 左节点
          if(leftNode === null && rightNode === null){
              continue;
          }
          if(leftNode === null || rightNode === null || leftNode.val !== rightNode.val){
              return false;
          }
          stack.push(leftNode.left);//左节点左孩子入队
          stack.push(rightNode.right);//右节点右孩子入队
          stack.push(leftNode.right);//左节点右孩子入队
          stack.push(rightNode.left);//右节点左孩子入队
      }
      return true;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    5.相同的树

    100. 相同的树-简单

    思路与对称二叉树一样,我这里用的队列,依次把两棵树对应位置的节点推入队列中进行比较。

    var isSameTree = function(p, q) {
        if(!p && !q) return true;
        if(!p || !q) return false;
        const queue = [p, q];
        while(queue.length) {
            let p1 = queue.shift(), q1 = queue.shift();
            if(!p1 && !q1){
                continue;
            }else if(!p1 || !q1){
                return false;
            }else if(p1.val === q1.val){
                queue.push(p1.left), queue.push(q1.left);
                queue.push(p1.right), queue.push(q1.right);
                continue;
            }else if(p1.val !== q1.val){
                return false;
            }
        }
        return true;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    简洁版👇

    var isSameTree = function(p, q) {
        if (p === null && q === null) {
            return true;
        } else if (p === null || q === null) {
            return false;
        } else if (p.val !== q.val) {
            return false;
        } else {
            return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    6.另一棵树的子树

    572. 另一棵树的子树-简单

    思路与对称二叉树一样。

    var isSubtree = function(root, subRoot) {
        if(!subRoot) return true;
        if(!root && subRoot) return false;
        const isSametree = function(tree, sub){
            if(!tree && !sub) return true;
            if(!tree || !sub) return false;
            if(tree.val !== sub.val) {
                return false;
            }
            return isSametree(tree.left, sub.left) && isSametree(tree.right, sub.right);
        }
        return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot) ||isSametree(root, subRoot);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    [笔记] 错排问题 #错排
    关于TreeView的简单使用(Qt6.4.1)
    用 Redis 做一个可靠的延迟队列
    用Windows性能监视器分析网站运行状况
    base64加密 > json字符串 > 中文转Unicode所遇问题
    mysql8.0修改用户密码
    从能用到好用,国产CPU不是你想象中的样子了?
    juc并发编程
    vim 不常见但好用的命令
    CentOS中安装常用环境
  • 原文地址:https://blog.csdn.net/weixin_44286392/article/details/126754782