树形结构-对应算法详解五

140 阅读8分钟

文章简要概述

  • 本文主要进行树相关的算法题刷题题解记录,记录树相关算法以及如何解。
  • 这文一共有8道题,主要介绍leetcode中二叉树的最大深度面试题 04.05. 合法二叉搜索树230. 二叉搜索树中第K小的元素199. 二叉树的右视图100. 相同的树101. 对称二叉树剑指 Offer 68 - I. 二叉搜索树的最近公共祖先二叉树中的最大路径和的解题思路。

与树相关算法

104. 二叉树的最大深度

104. 二叉树的最大深度--leetcode

题目大意:

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例

给定二叉树 [3,9,20,null,null,15,7]

   3
   / \
  9  20
    /  \
   15   7

解题思路:

  • 采用深度优先搜索、广度优先搜索都可以实现
  • 递归的方式,获取左右子树高度的最大值,再+1就是当前树的高度

代码:

/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function(root) {
    if (root === null) return 0
    return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;
};

面试题 04.05. 合法二叉搜索树

面试题 04.05. 合法二叉搜索树--leetcode

题目大意:

实现一个函数,检查一棵二叉树是否为二叉搜索树。

示例:

输入: 
    2
   / \
  1   3
输出: true

解题思路:

  • 二叉搜索树的规律是,根节点的值大于左子树的值,右子树的值大于根节点
  • 遍历树,比较上面的规律,不符合即返回false
  • 当遍历到空节点说明之前都是符合条件,即返回true

代码:

/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isValidBST = function(root) {
   return helper(root, -Infinity, Infinity)
};
function helper(root, lower, upper) {
    if (root === null) return true;
    if (root.val <= lower || root.val >= upper) return false;
    return helper(root.left, lower, root.val) && helper(root.right, root.val, upper);
}

230. 二叉搜索树中第K小的元素

230. 二叉搜索树中第K小的元素--leetcode

题目大意:

给定一个二叉搜索树的根节点 `root` ,和一个整数 `k` ,请你设计一个算法查找其中第 `k` ****个最小元素(从 1 开始计数)。

示例:

kthtree1.jpg

输入: root = [3,1,4,null,2], k = 1

输出: 1

解题思路:

  • 二叉搜索树的规律是左子树的值是当前树中值最小的值
  • 借助栈,先遍历左子树,放入到栈中
  • 弹栈,当k值为0。即找到第k小的值,否则把右子树放入到栈中
  • 循环操作直到符合k的值

代码:

/**
 * @param {TreeNode} root
 * @param {number} k
 * @return {number}
 */
var kthSmallest = function(root, k) {
  let stack = [];
  while(root !== null || stack.length) {
      while(root!== null) {
          stack.push(root);
          root = root.left;
      }
      root = stack.pop();
      k--;
      if (k === 0) {
          break;
      }
      root = root.right;
  }
  return root.val
};

199. 二叉树的右视图

199. 二叉树的右视图--leetcode

题目大意:

给定一个二叉树的 **根节点** `root`,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例:

tree.jpg

输入: [1,2,3,null,5,null,4]

输出: [1,3,4]

解题思路:

  • 找到树结构的每一层,寻找到最右侧的节点
  • 设置一个栈,存储每一层最右侧的值
  • 优先递归遍历右子树,当层数和栈的长度一致时,将当前节点放入到栈中
  • 递归完成,返回栈即可

代码:

/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var rightSideView = function(root) {
    let res = [];
    function dsf(root, deph) {
      if (!root) return [];
      if (deph === res.length) {
          res.push(root.val);
      }
      deph++
      dsf(root.right, deph);
      dsf(root.left, deph);
    }
    dsf(root, 0)
    return res
};

100. 相同的树

100. 相同的树--leetcode

题目大意:

给你两棵二叉树的根节点 `p` 和 `q` ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例:

ex1.jpg

输入: p = [1,2,3], q = [1,2,3] 输出: true

解题思路:

  • 比较当前节点的值是否都为空,如果都为空,说明之前遍历都是符合条件的,即返回true
  • 当前节点的值,其中一个为空,即两个节点不相同,返回false
  • 当前节点的值不相等,即两个节点不相同,返回false
  • 以上条件都符合,递归遍历两棵树,继续比较左子树与左子树,右子树与右子树的值

代码:

/**
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {boolean}
 */
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);
};

101. 对称二叉树

101. 对称二叉树--leetcode

题目大意:

给你一个二叉树的根节点 `root` , 检查它是否轴对称。

示例:

symtree1.jpg

输入: root = [1,2,2,3,4,4,3]

输出: true

解题思路:

  • 对称二叉树,即可得到左子树与右子树的值相同
  • 将树的左子树与右子树进行比较
  • 当都为空时,说明前面递归比较都符合条件,即返回true
  • 当其中一个为空时,不符合两个节点相等,即返回false
  • 当两个节点相等,继续递归比较左子树与右子树的值是否相同

代码:

/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function(root) {
  return check(root, root);
};
function check(p, q) {
    if (q == null && p == null) return true;
    if (!q || !p) return false;
    return p.val === q.val && check(p.left, q.right) && check(p.right, q.left);
}

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先--leetcode

题目大意:

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 pq,最近公共祖先表示为一个结点 x,满足 xpq 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树:  root[6,2,8,0,4,7,9,null,null,3,5]

示例:

binarysearchtree_improved.png

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8

输出: 6

解释: 节点 2 和节点 8 的最近公共祖先是 6。

解题思路:

  • 当前树是二叉搜索树,即左子树的值小于根节点小于右子树的值
  • 当p的值小于根节点的值,且q的值也小于根节点的值。即p和q的最近公共祖先在根节点左子树中
  • 当p的值大于根节点的值,且q的值也大于根节点的值。即p和q的最近公共祖先在根节点右子树中
  • 否则,当前节点就是最近公共祖先

代码:

/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
    while(root) {
        if (p.val < root.val && q.val < root.val) {
            root = root.left;
        } else if (p.val > root.val && q.val > root.val) {
            root = root.right;
        } else {
            break;
        }
    }
    return root;
};

124. 二叉树中的最大路径和

124. 二叉树中的最大路径和--leetcode

题目大意:

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例:

exx2.jpg

输入:root = [-10,9,20,null,null,15,7] 输出:42 解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

解题思路:

  • 先遍历左侧:Math.max(0,traverse(node.left));
  • 再遍历右侧:Math.max(0,traverse(node.right));
  • 在每个节点执行更新max:如果这条链路(左最大+右最大+当前节点值)比之前的max大,则更新max:Math.max(max,left+right+node.val)
  • 在每个节点返回当前节点的最大值和(可能在左侧,也可能在右侧):Math.max(left,right)+node.val

代码:

/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxPathSum = function(root) {
    let max = root.val;
    const traverse = (node)=>{
        if(node !== null){
            const left = Math.max(0,traverse(node.left));//左侧遍历
            const right = Math.max(0,traverse(node.right));//右侧遍历
            max = Math.max(max,left+right+node.val);//更新max
            return Math.max(left,right)+node.val//返回当前链路和
        }
        return 0 
    }
    traverse(root);
    return max  
};

结束语

数据结构与算法相关的练习题会持续输出,一起来学习,持续关注。当前是树部分。后期还会有其他类型的数据结构,题目来源于leetcode。

往期文章:

树形结构-对应算法详解一                             树形结构-对应算法详解二                             链表相关算法复习一

链表相关算法复习二                                      链表相关算法复习三                                      数据结构与算法-栈一

数据结构与算法-栈二                                    数据结构与算法-队列一                                数据结构与算法-队列二

数据结构与算法-链表一                                 数据结构与算法-链表二                                 数据结构与算法-链表三

有兴趣的可以一起来刷题,求点赞👍 关注!