二叉树 每层最大宽度和二叉树的高度

206 阅读3分钟

题目

求一个二叉树的最大宽度

  • 因为要求宽度,所以遍历方式选择宽度遍历,但是只是宽度遍历,无法知道当前节点的层级,便无法统计每层有多少个节点
    • 设置当前节点层级:从第一个节点开始,第一个节点的层级为1,当宽度遍历,往队列中放当前节点的左右子节点时,设置左右节点层级为当前节点层级+1
    • 因为是宽度遍历,当遍历到第一层时,放置到第二层的节点层级都已知晓,遍历第二层,放置第三层的节点层级都已知晓
    • 获取当前节点层级:在设置层级时,通过map来进行每个节点的层级映射,后续根据当前遍历的节点就能取出节点的层级,然后后进行统计高度和每层数量的操作
function BFS(head) {
  let arr = [];

  arr.push(head);
  //当前遍历到的层级
  let level = 1;
  //统计当前层的节点树
  let currentLeveNodesNum = 0;
  let max = 0;
  //通过map来映射每个节点的层级
  let map = new Map();
  map.set(head, level);

  for (let i = 0; i < head.length; i++) {
    let currentNodeLevel = map.get(arr[i]);
    //如果当前节点的层级和宽度优先遍历到的层级相同
    if (currentNodeLevel === level) {
      currentLeveNodesNum++;
    } else {
      //到了下一层
      max = Math.max(max, currentLeveNodesNum);
      level++;
      currentLeveNodesNum = 1;
    }
    if (arr[i].left) {
      //因为第一个节点知道自己的层级,所以它的子节点就是当前节点+1
      //那之后的每个节点的层级,都可以通过它的上层节点来设置
      map.set(arr[i].left, currentNodeLevel + 1);
      arr.push(arr[i].left);
    }
    if (arr[i].right) {
      map.set(arr[i].right, currentNodeLevel + 1);
      arr.push(arr[i].right);
    }
  }
  return [level,max]
}

不用map结构的方法

  • 一定能够通过当前层的最后一个节点,知道下一层的最后一个节点,因为下一层最后一个节点是它的左节点或右节点
  • 从第一个节点开始,一定知道第二层的最后一个节点,记录第二层的最后一个节点,当遍历到的节点,如果节点等于之前记录的第二层的最后一个节点,说明第二层遍历完了,进行统计宽度等操作,同时一定能够通过该节点知道第三层的最后一个节点,第三层同样进行这样的判断,之后类似。
function BFS2(head) {
  let arr = [];

  arr.push(head);
  //当前遍历到的层级
  let level = 1;

  let currentLevelNodeNum = 0;
  let max = 0;

  let curentLevelEndNode = head;
  let nextLevelEndNode = null;

  //每次通过nextLevelEndNode记录下一层的最后一个子节点
  //当本次遍历的节点==curentLevelEndNode即记录的最后一层节点时,进行最大宽度计算等统计
  //因为当遍历到当前层的最后一个节点时,一定能够通过该节点知道下一层的最后一个节点
  //所以curentLevelEndNode和nextLevelEndNode互换
  for (let i = 0; i < head.length; i++) {
    if (arr[i].left) {
      nextLevelEndNode = arr[i].left;
      arr.push(arr[i].left);
    }
    if (arr[i].right) {
      nextLevelEndNode = arr[i].right;
      arr.push(arr[i].right);
    }
    //遍历到了当前层的最后一个节点
    //将最后一个节点的子节点(上方遍历时记录的)给curentLevelEndNode标志下一层的最后一个节点
    if (arr[i] == curentLevelEndNode) {
      curentLevelEndNode = nextLevelEndNode;
      if (nextLevelEndNode != null) {
        level++;
      }
      curentLevelEndNodeNUm++;
      max = Math.max(max, currentLevelNodeNum);
      currentLevelNodeNum = 0;
    } else {
      currentLevelNodeNum++;
    }
  }

  return [level, max];
}