26. 树的子结构

链接

https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof/
难度: #中等

题目

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如:
给定的树 A:

3
    / \
   4   5
  / \
 1   2

给定的树 B:

4 
  /
 1

返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

示例 1:

输入:A = [1,2,3], B = [3,1]
输出:false

示例 2:

输入:A = [3,4,5,1,2], B = [4,1]
输出:true

限制:0 <= 节点个数 <= 10000

代码框架

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {

    }
}

题目解析

1.创建一个辅助函数判断两棵树是否相等
2.递归遍历A树的每一个节点作为根结点和B树进行比较
3.每次遇到A的节点与B的头结点相同,则继续比较A和B的子节点

解答思路1:
在二叉树A中先序遍历,
找到第一个和B的第一个相同的节点,
然后比较其左右子节点是否相同,
如果B没有左或者右节点,则无需比较,
直接返回true,
如果A没有子节点,B有子节点,则一定不是,
直接返回false。

解答思路2:
解答思路1的代码优化写法,
利用了&&和||逻辑运算符的快速返回特性,
在二叉树A中先序遍历,
找到第一个和B的第一个相同的节点,
然后比较其左右子节点是否相同,
如果B没有左或者有节点,则无需比较。

测试用例

package edu.yuwen.sowrd.num26.solution;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import edu.yuwen.sowrd.entity.TreeNode;
import edu.yuwen.sowrd.num26.sol1.Solution;

public class SolutionTest {

    /**
     * 示例 1:
     * 输入:A = [1,2,3], B = [3,1]
     * 输出:false
     */
    @Test
    public void testCase1() {
        Solution solution = new Solution();
        TreeNode a = getTreeNodeA1();
        TreeNode b = getTreeNodeB1();
        boolean res = solution.isSubStructure(a, b);
        Assertions.assertEquals(false, res);
    }

    /**
     * 示例 2:
     * 输入:A = [3,4,5,1,2], B = [4,1]
     * 输出:true
     */
    @Test
    public void testCase2() {
        Solution solution = new Solution();
        TreeNode a = getTreeNodeA2();
        TreeNode b = getTreeNodeB2();
        boolean res = solution.isSubStructure(a, b);
        Assertions.assertEquals(true, res);
    }

    /**
     *       1
     *      / \
     *     2   3
     */
    public TreeNode getTreeNodeA1() {
        TreeNode node1 = new TreeNode(1);
        TreeNode node2 = new TreeNode(2);
        TreeNode node3 = new TreeNode(3);

        node1.left = node2;
        node1.right = node3;

        return node1;
    }

    /**
     *       3
     *      / 
     *     1   
     */
    public TreeNode getTreeNodeB1() {
        TreeNode node1 = new TreeNode(3);
        TreeNode node2 = new TreeNode(1);

        node1.left = node2;
        return node1;
    }

    /**
     *     3
     *    / \
     *   4   5
     *  / \
     * 1   2
     */
    public TreeNode getTreeNodeA2() {
        TreeNode node1 = new TreeNode(3);
        TreeNode node2 = new TreeNode(4);
        TreeNode node3 = new TreeNode(5);
        TreeNode node4 = new TreeNode(1);
        TreeNode node5 = new TreeNode(2);

        node1.left = node2;
        node1.right = node3;

        node2.left = node4;
        node2.right = node5;

        return node1;
    }

    /**
     *       4
     *      / 
     *     1   
     */
    public TreeNode getTreeNodeB2() {
        TreeNode node1 = new TreeNode(4);
        TreeNode node2 = new TreeNode(1);

        node1.left = node2;
        return node1;
    }
}

解答1

package edu.yuwen.sowrd.num26.sol1;

import edu.yuwen.sowrd.entity.TreeNode;

public class Solution {
    public boolean isSubStructure(TreeNode a, TreeNode b) {
        if (a == null || b == null) {
            return false;
        }

        // 比较当前节点及其子节点
        boolean cur = compare(a, b);
        // 确定是子结构即可返回
        if (cur) {
            return true;
        }

        // 否则遍历左右子树
        if (a.left != null) {
            boolean left = isSubStructure(a.left, b);
            // 只要相等了,即可返回
            if (left) {
                return true;
            }
        }

        if (a.right != null) {
            boolean right = isSubStructure(a.right, b);
            if (right) {
                return true;
            }
        }

        return false;
    }

    // 比较两颗二叉树是否相同
    private boolean compare(TreeNode a, TreeNode b) {
        // base case
        if (a == null) {
            if (b == null) {
                return true;
            }
            return false;
        }

        if (a != null && b == null) {
            return true;
        }

        // 比较当前值
        boolean cur = a.val == b.val;
        // 只要有一个节点不同,即可返回
        if (!cur) {
            return false;
        }

        // 比较左节点
        boolean left = compare(a.left, b.left);
        if (!left) {
            return false;
        }

        // 比较右节点
        boolean right = compare(a.right, b.right);
        if (!right) {
            return false;
        }

        // 当前和左右节点都相同,才认为相同
        return true;
    }
}

解答2 推荐

package edu.yuwen.sowrd.num26.sol2;

import edu.yuwen.sowrd.entity.TreeNode;

public class Solution {
    public boolean isSubStructure(TreeNode a, TreeNode b) {
        if (a == null || b == null) {
            return false;
        }

        // 先序遍历二叉树A, 比较当前节点及其子节点
        // 确定是子结构即可返回
        // 否则遍历二叉树a下一个节点
        return compare(a, b) || isSubStructure(a.left, b)
                || isSubStructure(a.right, b);
    }

    // 比较两颗二叉树是否相同
    private boolean compare(TreeNode a, TreeNode b) {
        // base case
        // b为null,则一定相同
        if (b == null) {
            return true;
        }
        // b不为null,但a为null,则一定不同
        else if (a == null) {
            return false;
        }

        // 比较当前值, 比较左节点,比较右节点
        // 当前和左右节点都相同,才认为相同
        // 否则只要有一个节点不同,即可返回
        return a.val == b.val && compare(a.left, b.left)
                && compare(a.right, b.right);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值