算法刷题 | 树

133 阅读2分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

树的结构十分直观,而树的很多概念定义都有一个相同的特点:递归,也就是说,一棵树要满足某种性质,往往要求每个节点都必须满足。例如,在定义一棵二叉搜索树时,每个节点也都必须是一棵二叉搜索树。

正因为树有这样的性质,大部分关于树的面试题都与递归有关。

树的形状

在面试中常考的树的形状有:普通二叉树、平衡二叉树、完全二叉树、二叉搜索树、四叉树(Quadtree)、多叉树(N-ary Tree)。

对于一些特殊的树,例如红黑树(Red-Black Tree)、自平衡二叉搜索树(AVL Tree),一般在面试中不会被问到,除非你所涉及的研究领域跟它们相关或者你十分感兴趣,否则不需要特别着重准备。

关于树的考题,无非就是要考查树的遍历以及序列化(serialization)。

题目1:树的层次遍历

解题思路

层次遍历是对树的每一层的结点进行遍历。层次遍历是广度优先遍历

代码实现

function treeNode(val) {
    this.val = val; // 当前结点的值
    this.left = null; //指向左子节点
    this.right = null; //指向右子节点
}
​
var treeSearch = function(root) {
    if(!root)   return [];
     let res = [];
     let q = [root];
     while(q.length > 0){
         let tmp = [];
         let temp = [];
         for(let i in q){
             let p = q[i];
             temp.push(p.val);
             p.left && tmp.push(p.left);
             p.right && tmp.push(p.right);
         }
         q = tmp;
         res.push(temp);
     }
     return res;
 };

题目2 : 判断二叉树 A 中是否包含子树 B

解题思路

查找A树中是否存在B树的结构一样的子树,需要B树中的结点都存在于A树中。需要使用2个递归

第一步:在A树中找到和B树的根结点一样的结点值C,如果没有说明不存在。此过程可以使用递归的方法遍历或者循环的方法遍历

第二步:判断A树中以结点C为结点的子结点是否和B树子节点一样,如果存在不一样,继续寻找看是否存在其他结点和B树的根结点一样。

代码实现

function isExistTree(node, tNode) {
     if (!tNode) return true;
​
     if (!node) return false;
​
     if (node.val === tNode.val &&  findNode(node.left, tNode.left)&& findNode(node.right, tNode.right)) {
         return true
     } else {
          isExistTree(node.left,tNode) || isExistTree(node.right,tNode)
     }
}
​
function findNode(A, B) {
     if (!A) return false
     if (!B) return true
​
     if (A.val !== B.val) {
          return false
     }
     return find(A.left, B.left) && find(A.right, B.right)
}