• 剑指offer


    1.重建二叉树

    问题描述:

    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

    /* function TreeNode(x) {
        this.val = x;
        this.left = null;
        this.right = null;
    } */
    
    function reConstructBinaryTree(pre, vin) {
      // write code here
      if (pre.length == 0 || vin.length == 0) {
        return null;
      }
      var root = pre[0]; //根节点
      var index = vin.indexOf(root); //在vin中找到根节点的索引
      var left = vin.slice(0, index); //左子树
      var right = vin.slice(index + 1); //右子树
      var node = new TreeNode(root); //新建一个二叉树
      node.left = reConstructBinaryTree(pre.slice(1, index + 1), left); //左子树的前序和中序
      node.right = reConstructBinaryTree(pre.slice(index + 1), right); //右子树的前序和中序
      return node;
    }
    

    2.二叉树的下一个结点

    给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

    解题思路:

    分析二叉树的下一个节点,一共有以下情况:

    1.二叉树为空,则返回空;

    2.有右子树的,那么下个结点就是右子树最左边的点

    3.没有右子树的,也可以分成两类:

    • 是父节点左孩子,那么父节点就是下一个节点
    • 是父节点的右孩子,找他的父节点的父节点的父节点...直到当前结点是其父节点的左孩子位置,下一个结点就是当前结点
    /*function TreeLinkNode(x){
        this.val = x;
        this.left = null;
        this.right = null;
        this.next = null;
    }*/
    
    function GetNext(pNode) {
      // write code here
      if (pNode === null) return null; //空结点
      var p = null;
      if (pNode.right) {
        //有右子树,则下一个结点在右子树最左边的结点
        p = pNode.right;
        while (p.left !== null) {
          p = p.left;
        }
        return p;
      } else {
        //没有右子树
        p = pNode.next;
        if (p && p.right === pNode) {
          while (p.next && p.next.right === p) {
            p = p.next;
          }
          p = p.next;
        }
        return p;
      }
      return null;
    }
    

    3.对称的二叉树

    问题描述:

    请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。空二叉树也是对称的。

    解题思路:

    空二叉树也是对称的,这是值得注意的点。

    然后将二叉树一层一层比较一下

    /* function TreeNode(x) {
        this.val = x;
        this.left = null;
        this.right = null;
    } */
    
    function isSymmetrical(pRoot) {
      // write code here
      if (!pRoot) return true; // 注意是true
      return judge(pRoot.left, pRoot.right);
    }
    
    function judge(node1, node2) {
      //判断这两个结点以及子节点是否对称
      if (node1 === null && node2 === null) {
        return true;
      } else if (node1 === null || node2 === null) {
        return false;
      }
      if (node1.val !== node2.val) {
        return false;
      } else {
        return judge(node1.left, node2.right) && judge(node1.right, node2.left);
      }
    }
    

    4.按之字形顺序打印二叉树

    问题描述:

    请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。空二叉树输出空数组。

    输入:

    输出:
    [[8],[10,6],[5,7,9,11]]

    /* function TreeNode(x) {
        this.val = x;
        this.left = null;
        this.right = null;
    */
    
    function Print(pRoot) {
      // write code here
      if (!pRoot) return [];
      const nodes = []; //结点
      const vals = []; //val
      var flag = true; //true代表顺序打印
      nodes.push(pRoot);
      while (nodes.length) {
        var temp = [];
        var len = nodes.length; //这里注意要先把nodes的长度赋值给一个变量,因为下面循环中nodes里会添加新的结点
        for (let i = 0; i < len; i++) {
          var node = nodes.shift(); //每次弹出nodes中第一个结点
          flag === true ? temp.push(node.val) : temp.unshift(node.val);
          if (node.left) {
            nodes.push(node.left);
          }
          if (node.right) {
            nodes.push(node.right);
          }
        }
        flag = !flag;
        vals.push(temp);
      }
      return vals;
    }
    

    5.把二叉树打印成多行

    问题描述:

    从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

    输入:

    输出:
    [[8],[6,10],[5,7,9,11]]

    /* function TreeNode(x) {
        this.val = x;
        this.left = null;
        this.right = null;
    } */
    
    function Print(pRoot) {
      // write code here'
      if (!pRoot) return [];
      const nodes = [];
      const vals = [];
      nodes.push(pRoot);
      while (nodes.length) {
        var len = nodes.length;
        var temp = [];
        for (let i = 0; i < len; i++) {
          var node = nodes.shift();
          temp.push(node.val);
          if (node.left) {
            nodes.push(node.left);
          }
          if (node.right) {
            nodes.push(node.right);
          }
        }
        vals.push(temp);
      }
      return vals;
    }
    

    6.序列化二叉树

    问题描述:

    请实现两个函数,分别用来序列化和反序列化二叉树

    二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。

    二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果 str,重构二叉树。

    /* function TreeNode(x) {
        this.val = x;
        this.left = null;
        this.right = null;
    } */
    
    var arr = [];
    function Serialize(pRoot) {
      // write code here
      if (!pRoot) {
        arr.push("#");
      } else {
        arr.push(pRoot.val);
        Serialize(pRoot.left);
        Serialize(pRoot.right);
      }
    }
    function Deserialize(s) {
      // write code here
      if (arr === null) return null;
      if (arr.length < 1) return null;
      var root = null;
      var temp = arr.shift();
      if (typeof temp === "number") {
        root = new TreeNode(temp);
        root.left = Deserialize(arr);
        root.right = Deserialize(arr);
      }
      return root;
    }
    

    7.二叉搜索树的第 k 个结点

    题目描述:

    给定一棵二叉搜索树,请找出其中的第 k 小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为 4。

    解题思路:

    二叉搜索树的特性:左子树 < 根节点 < 右子树

    故只需要找出二叉搜索树的中序,然后找第 k 个结点

    /* function TreeNode(x) {
        this.val = x;
        this.left = null;
        this.right = null;
    } */
    function KthNode(pRoot, k) {
      // write code here
      var arr = []; //中序存储结点
      // 中序函数
      function mid(pRoot) {
        if (!pRoot) return null;
        mid(pRoot.left);
        arr.push(pRoot);
        mid(pRoot.right);
      }
      // 调用中序函数
      mid(pRoot);
      return arr[k - 1];
    }
    

    8.数据流中的中位数

    问题描述:

    如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用 Insert()方法读取数据流,使用 GetMedian()方法获取当前读取数据的中位数。

    var arr = [];
    function Insert(num) {
      // write code here
      arr.push(num);
      var i = arr.length - 1;
      while (i > 0) {
        if (arr[i] < arr[i - 1]) {
          [arr[i], arr[i - 1]] = [arr[i - 1], arr[i]];
        }
        i--;
      }
      return arr;
    }
    function GetMedian() {
      // write code here
      if (!arr.length) return null;
      var length = arr.length;
      var mid = parseInt(length / 2);
      if (length % 2 === 0) {
        var avg = (arr[mid - 1] + arr[mid]) / 2;
        return avg;
      } else {
        return arr[mid];
      }
    }
    
  • 相关阅读:
    Python自学教程1安装pycharm和执行环境
    软件测试100天上岸3测试有哪些最高原则
    Python自学教程2:大牛们怎么写注释
    软件测试100天上岸2测试必须有策略
    学自动化测试可以用这几个练手项目
    嵌入式系统测试思路
    软件测试100天上岸1测试就是找茬游戏
    Postman如何做接口测试,那些不得不知道的技巧
    【Vue】vue3 部分组件手动刷新也无法热更新
    【JavaScript】手写深拷贝 2.0(更新 20220715)
  • 原文地址:https://www.cnblogs.com/muzidaitou/p/12712622.html
Copyright © 2020-2023  润新知