当前位置: 首页 > article >正文

数据结构与算法之二叉树: LeetCode 572. 另一棵树的子树 (Ts版)

另一棵树的子树

  • https://leetcode.cn/problems/subtree-of-another-tree/description/

描述

  • 给你两棵二叉树 root 和 subRoot
  • 检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树
  • 如果存在,返回 true ;否则,返回 false
  • 二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点
  • tree 也可以看做它自身的一棵子树

示例 1

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

示例 2

输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false

提示

  • root 树上的节点数量范围是 [1, 2000]
  • subRoot 树上的节点数量范围是 [1, 1000]
  • - 1 0 4 10^4 104 <= root.val <= 1 0 4 10^4 104
  • - 1 0 4 10^4 104 <= subRoot.val <= 1 0 4 10^4 104

Typescript 版算法实现


1 ) 方案1:深度优先搜索暴力匹配

/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     val: number
 *     left: TreeNode | null
 *     right: TreeNode | null
 *     constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.left = (left===undefined ? null : left)
 *         this.right = (right===undefined ? null : right)
 *     }
 * }
 */

function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean {
    if (!root) return false;
    return check(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}
 
function check(a: TreeNode | null, b: TreeNode | null): boolean {
    if (!a && !b) return true;
    if (!a || !b) return false;
    if (a.val === b.val) return check(a.left, b.left) && check(a.right, b.right);
    return false;
}

2 ) 方案2:深度优先搜索序列上做串匹配

/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     val: number
 *     left: TreeNode | null
 *     right: TreeNode | null
 *     constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.left = (left===undefined ? null : left)
 *         this.right = (right===undefined ? null : right)
 *     }
 * }
 */

function getMaxElement(root: TreeNode | null, maxElement: { value: number }): void {
    if (!root) return;
    maxElement.value = Math.max(maxElement.value, root.val);
    getMaxElement(root.left, maxElement);
    getMaxElement(root.right, maxElement);
}

function getDfsOrder(root: TreeNode | null, order: number[], lNull: number, rNull: number): void {
    if (!root) return;
    order.push(root.val);
    if (root.left) {
        getDfsOrder(root.left, order, lNull, rNull);
    } else {
        order.push(lNull);
    }
    if (root.right) {
        getDfsOrder(root.right, order, lNull, rNull);
    } else {
        order.push(rNull);
    }
}

function kmp(sOrder: number[], tOrder: number[]): boolean {
    const sLen = sOrder.length, tLen = tOrder.length;
    const fail: number[] = new Array(tLen).fill(-1);

    for (let i = 1, j = -1; i < tLen; ++i) {
        while (j !== -1 && tOrder[i] !== tOrder[j + 1]) {
            j = fail[j];
        }
        if (tOrder[i] === tOrder[j + 1]) {
            ++j;
        }
        fail[i] = j;
    }

    for (let i = 0, j = -1; i < sLen; ++i) {
        while (j !== -1 && sOrder[i] !== tOrder[j + 1]) {
            j = fail[j];
        }
        if (sOrder[i] === tOrder[j + 1]) {
            ++j;
        }
        if (j === tLen - 1) {
            return true;
        }
    }

    return false;
}

function isSubtree(s: TreeNode | null, t: TreeNode | null): boolean {
    let maxElement = Number.MIN_SAFE_INTEGER;
    getMaxElement(s, { value: maxElement });
    getMaxElement(t, { value: maxElement });

    const lNull = maxElement + 1;
    const rNull = maxElement + 2;

    const sOrder: number[] = [];
    const tOrder: number[] = [];

    getDfsOrder(s, sOrder, lNull, rNull);
    getDfsOrder(t, tOrder, lNull, rNull);

    return kmp(sOrder, tOrder);
}

3 ) 方案3:基于两棵树是否相同来判断

/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     val: number
 *     left: TreeNode | null
 *     right: TreeNode | null
 *     constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.left = (left===undefined ? null : left)
 *         this.right = (right===undefined ? null : right)
 *     }
 * }
 */

function isSubtree(root:TreeNode | null, subRoot:TreeNode | null) {
  // 不停地比较, 某一个子树,是不是和subRoot一样
  if(!root) return false
  if((root.val === subRoot.val) && (isSameTree(root,subRoot))) return true
  return isSubtree(root.left,subRoot) || isSubtree(root.right,subRoot)
};

function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
  if(!p && !q) return true
  if(!p || !q) return false
  if(p.val!==q.val) return false
  return isSameTree(p.left,q.left) && isSameTree(p.right,q.right)
};

http://www.kler.cn/a/501392.html

相关文章:

  • 六十九:基于openssl实战验证RSA
  • WPF中如何在MVVM模式下跨线程更新UI
  • 人工智能实验(四)-A*算法求解迷宫寻路问题实验
  • 【2024年华为OD机试】(C卷,100分)- 攀登者1 (Java JS PythonC/C++)
  • redisson分布式锁关的疑问和解答记录
  • 【数据库】四、数据库管理与维护
  • 1、什么是GO
  • IntelliJ IDEA 优化设置
  • 啥!GitHub Copilot也免费使用了
  • 晨辉面试抽签和评分管理系统之七:面试成绩核算的三种方式
  • matlab编写分段Hermite插值多项式
  • linux新磁盘做分区(GPT分区表)
  • MySQL教程之:批量使用mysql
  • MyBatis-Plus自动填充
  • Node.js——fs(文件系统)模块
  • Android车机DIY开发之软件篇(九)默认应用和服务修改
  • gesp(C++四级)(16)洛谷:B4069:[GESP202412 四级] 字符排序
  • Oracle 23ai新特性:表值构造函数
  • 《自动驾驶与机器人中的SLAM技术》ch7:基于 ESKF 的松耦合 LIO 系统
  • 全栈面试(一)Basic/微服务
  • 基于django车牌识别系统(源码+lw+部署文档+讲解),源码可白嫖!
  • C++实现设计模式---模板方法模式 (Template Method)
  • Git的master 分支和main分支的区别是什么?使用场景是什么?底层原理是什么?
  • nginx负载均衡-基于端口的负载均衡(一)
  • 提升 PHP 编码效率的 10 个实用函数
  • 基于改进粒子群优化的无人机最优能耗路径规划