LeetCode刷题之旅(中等 -4):100. 相同的树

leetcode hot100 中等难度 day04-刷题 阅读详情

2019年9月15日

继续弥补《数据结构与算法》的不足,今天抽中了“树”。决定先把基础题做一遍,打好基础。

目录

题目:

解决方法1:

解决思路:

性能结果:

解决方法2:

思路:深度优先遍历

解决方法3:

迭代

复杂度分析

递归

复杂度分析


题目:

 

二叉树基础概念:

树是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由 n(n>0)n(n>0) 个有限节点组成一个具有层次关系的集合。

把它叫做「树」是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

它具有以下的特点:

  • 每个节点都只有有限个子节点或无子节点;
  • 没有父节点的节点称为根节点;
  • 每一个非根节点有且只有一个父节点;
  • 除了根节点外,每个子节点可以分为多个不相交的子树;
  • 树里面没有环路。

image.png

解决方法1:

package leetCode.tree;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * REMARK 相同的树
 *
 * @author: mmb
 * @date: 19-9-15
 */
public class TwoSameTreeSolution {

    public static void main(String[] args){
		TreeNode p = getATree();
//		TreeNode q = getATree();
		TreeNode q = getATreeV2();
		System.out.println("result = " + isSameTree(p, q));

	}

	/**
	 * 比较两棵树是否相同
	 */
    public static boolean isSameTree(TreeNode p, TreeNode q){
		List<Integer> tree1AllNodes = getAllNodes(p);
		List<Integer> tree2AllNodes = getAllNodes(q);
		System.out.println("tree1AllNodes = " + tree1AllNodes);
		System.out.println("tree2AllNodes = " + tree2AllNodes);
		return compareTwoTree(tree1AllNodes, tree2AllNodes);
    }

    /**
	 * 比较两棵树的结点列表
	 */
	private static boolean compareTwoTree(List<Integer> tree1AllNodes, List<Integer> tree2AllNodes) {
		// 两棵树的节点要一样
		if (tree1AllNodes.size() == tree2AllNodes.size()){
			int countTime = 0;
			int tree1NotNullCount = 0;
			int tree2NotNullCount = 0;
			Iterator<Integer> iterator1 = tree1AllNodes.iterator();
			Iterator<Integer> iterator2 = tree2AllNodes.iterator();
			// 逐个遍历两棵树的节点
			while (iterator1.hasNext()){
				Integer tree1Node = iterator1.next();
				Integer tree2Node = iterator2.next();

				// 两棵树的节点都不为空
				if (tree1Node != null && tree2Node != null){
					if (tree1Node.equals(tree2Node)){
						countTime++;
						continue;
					} else {
						break;
					}
				}
				// 两棵树的节点都为空
				else if (tree1Node == null && tree2Node == null) {
					continue;
				}
				// 其中一棵树节点为空
				else {
					break;
				}
			}

			// tree1的非空节点
			for (Integer node : tree1AllNodes){
				if (node != null){
					tree1NotNullCount++;
				}
			}
			// tree2的非空节点
			for (Integer node : tree2AllNodes){
				if (node != null){
					tree2NotNullCount++;
				}
			}

			// tree1和tree2和节点比较相同次数一样
			if (tree1NotNullCount == countTime && tree2NotNullCount == countTime){
				return true;
			}
		}
		return false;
	}

	/**
	 * 获取所有节点数据
	 */
	private static List<Integer> getAllNodes(TreeNode node){
		// 前序遍历,递归获取所有节点信息
		ArrayList<Integer> treeNodes = new ArrayList<>();
		if(node != null){
			treeNodes.add(node.val);
			if (node.left != null){
				List<Integer> allLeftNodes = getAllNodes(node.left);
				treeNodes.addAll(allLeftNodes);
			} else if (node.right != null){
				treeNodes.add(null);
			}

			if (node.right != null){
				List<Integer> allRightNodes = getAllNodes(node.right);
				treeNodes.addAll(allRightNodes);
			}

		}
		return treeNodes;
	}

	/**
	 * 创建一棵树
	 */
    public static TreeNode getATree(){
		TreeNode headNode = new TreeNode(1);
		TreeNode leftNode = new TreeNode(2);
		TreeNode rightNode = new TreeNode(3);
		headNode.setLeft(leftNode);
		headNode.setRight(rightNode);
		return headNode;
	}
    public static TreeNode getATreeV2(){
		TreeNode headNode = new TreeNode(1);
		TreeNode leftNode = new TreeNode(2);
		TreeNode rightNode = new TreeNode(3);
		headNode.setLeft(leftNode);
		headNode.setRight(rightNode);
		return headNode;
	}

}

解决思路:

  • 对于给定的两棵树,我是首先想到的是递归遍历(这里使用前序遍历:根节点-左子树-右子树),也就是说将树的所有节点全部拿出到list里面;第二步,就是逐个对比list的节点是否相同;
  • 这种方法比较笨,我这种初学者往往会往死胡同里面走;这时候算法体现出优越性了。。。

性能结果:

解决方法2:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p == null && q == null) 
            return true;
        if(p == null || q == null) 
            return false;
        if(p.val != q.val) 
            return false;
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }
}

作者:guanpengchn
链接:https://leetcode-cn.com/problems/same-tree/solution/hua-jie-suan-fa-100-xiang-tong-de-shu-by-guanpengc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

思路:深度优先遍历

终止条件与返回值:

  • 当两棵树的当前节点都为 null 时返回 true
  • 当其中一个为 null 另一个不为 null 时返回 false
  • 当两个都不为空但是值不相等时,返回 false

执行过程:当满足终止条件时进行返回,不满足时分别判断左子树和右子树是否相同,其中要注意代码中的短路效应

时间复杂度:O(n),n 为树的节点个数

 

解决方法3:

迭代

  • 最简单的策略是使用递归。检查p和q节点是否不是空,它们的值是否相等。如果所有检查都正常,则递归地为子节点执行相同操作。
class Solution {
  public boolean isSameTree(TreeNode p, TreeNode q) {
    // p 和 q 均为 null时
    if (p == null && q == null) return true;
    // p 或 q 有一个为null时
    if (q == null || p == null) return false;
    if (p.val != q.val) return false;
    return isSameTree(p.right, q.right) &&
            isSameTree(p.left, q.left);
  }
}

作者:gaohanghang
链接:https://leetcode-cn.com/problems/same-tree/solution/xiang-tong-de-shu-by-gaohanghang/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

复杂度分析

时间复杂度:O(N),其中N是树中的节点数,因为每个节点只访问一次。

空间复杂度:O(log(N)):

在最佳情况下即completely balanced tree空间复杂度是O(log(N)),

在最坏情况下 completely unbalanced tree空间复杂度是O(N),和递归次数保持一致。

 

递归

  • 思路:从根开始,在每次迭代时将当前节点弹出deque。

  • 然后执行与方法1中相同的检查:p 和 q 不为空,p.val 和 q.val 相等,如果检查正常,则push子节点。

class Solution {
  public boolean check(TreeNode p, TreeNode q) {
    // p and q are null
    if (p == null && q == null) return true;
    // one of p and q is null
    if (q == null || p == null) return false;
    if (p.val != q.val) return false;
    return true;
  }

  public boolean isSameTree(TreeNode p, TreeNode q) {
    if (p == null && q == null) return true;
    if (!check(p, q)) return false;

    // init deques
    ArrayDeque<TreeNode> deqP = new ArrayDeque<TreeNode>();
    ArrayDeque<TreeNode> deqQ = new ArrayDeque<TreeNode>();
    deqP.addLast(p);
    deqQ.addLast(q);

    while (!deqP.isEmpty()) {
      p = deqP.removeFirst();
      q = deqQ.removeFirst();

      if (!check(p, q)) return false;
      if (p != null) {
        // in Java nulls are not allowed in Deque
        if (!check(p.left, q.left)) return false;
        if (p.left != null) {
          deqP.addLast(p.left);
          deqQ.addLast(q.left);
        }
        if (!check(p.right, q.right)) return false;
        if (p.right != null) {
          deqP.addLast(p.right);
          deqQ.addLast(q.right);
        }
      }
    }
    return true;
  }
}

作者:gaohanghang
链接:https://leetcode-cn.com/problems/same-tree/solution/xiang-tong-de-shu-by-gaohanghang/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

复杂度分析

时间复杂度 :O(N) 因为每个节点只访问一次
空间复杂度:O(log(N)), 在最佳情况下即completely balanced tree空间复杂度是O(log(N)),在最坏情况下 completely unbalanced tree空间复杂度是O(N)

 

Leetcode-How-What 力扣Leetcode刷题指南 Leetcode-How-What 力扣Leetcode刷题指南 About the way how to use Leetcode wisely for preparing the interview and the solutions to some Leetcode problems’. 怎样为准备面试机智聪明的刷题(高效刷题)以及一些题目的题解。 同 github 链接: https:/... 阅读详情

相关推荐

leetcode hot100 中等难度 day03-刷题

leetcode hot100 中等难度 day03-刷题

weixin_46676835的博客 1622

力扣(LeetCode)怎么刷题,以排序算法为例

掌握 LeetCode 刷题方法再开始刷题,属于磨刀不误砍柴工。掌握正确方法是非常重要的。 如果你在刷题的时候发现怎么也写不出来,别担心,这是正常的。如果你还发现,之前明明刷过的题,过段时间再做的时候,自己还是不会。别担心,这也是正常的。 在这我分享一下我的刷题经验,希望对你有帮助。如果你时间比较紧迫,为了找工作而刷题,我建议你先刷热门推荐,一共两百多道题。 在 LeetCode中文版 页面的右侧。先刷热题 HOT 100,再刷精选 TOP 面试题,之后刷其他的题。 如果你时间比较充裕,那我建议

Allenzyg的博客 1万+

力扣热题100刷题笔记[python]

力扣100刷题题解

仰望星空 2166

力扣刷题之准备工作

在刷算法题的过程中进行总结是非常重要的,它可以帮助你梳理思路、加深理解、记录学习成果,并提升解题能力。每天回顾:在每天结束时,对当天解决的题目进行回顾。检查解决方案的正确性,并思考是否有更优化的方法。记录下遇到的难点和解决方法,以及学到的新知识点和技巧。整理这些笔记并归档到适当的分类中,以便今后参考。每周汇总:在每周末或开始新一周时进行总结。复习过去一周解决的题目,分析解题过程中使用的算法和数据结构。总结你学到的关键知识点、解题技巧和模式,并将其整理到博客中。

weixin_47040031的博客 9753

LeetCode Hot100 刷题笔记(4)—— 二叉树、图论

一、二叉树:二叉树的中序遍历,二叉树的最大深度,翻转二叉树,对称二叉树,二叉树的直径,二叉树的层序遍历,将有序数组转换为二叉搜索树,验证二叉搜索树,二叉搜索树中第 K 小的元素,二叉树的右视图,二叉树展开为链表,从前序与中序遍历序列构造二叉树,路径总和 III,二叉树的最近公共祖先,二叉树中的最大路径和。 二、图论:岛屿数量,腐烂的橘子,课程表,实现 Trie (前缀树)。

qq_51175703的博客 1592

力扣hot100二刷——链表

第二次刷题不在idea写代码,而是直接在leetcode网站上写,“逼”自己掌握常用的函数。

weixin_49426115的博客 1822

Leetcode刷题修炼手册

我的机器学习教程「美团」算法工程师带你入门机器学习 已经开始更新了,欢迎大家订阅~ 任何关于算法、编程、AI行业知识或博客内容的问题,可以随时扫码关注公众号「图灵的猫」,加入”学习小组“,沙雕博主在线答疑~此外,公众号内还有更多AI、算法、编程和大数据知识分享,以及免费的SSR节点和学习资料。其他平台(知乎/B站)也是同名「图灵的猫」,不要迷路哦~ “跟着...

Machine Learning with Tutors 5万+

前端JavaScript力扣HOT100刷题【51-100】

注:纯手打,如有错误欢迎评论区交流!编写此文是为了更好地学习前端知识,如果损害了有关人的利益,请联系删除!本文章将不定时更新,敬请期待!!!!!

testleaf.cn 1009

LeetCode第100题_相同的树

给你两棵二叉树的根节点p和q,编写一个函数来检验这两棵树是否相同。如果两棵树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

qq_40263592的博客 1722

1024,给大家谈谈如何搞透刷题 玩转力扣!

前言 大家好,我是bigsai,好久不见!今天1024,祝大家程序员节快乐,写代码永没bug!今天就给各位小伙伴分享我自己刷题力扣的一些小方法,不一定很有用但是可以参考,祝你更高效的变强! 最近在一些群聊、私聊中遇到很多的一个问题就是:刷题,大家也都重视到算法刷题对冲击大厂的重要性,越来越多的人开始卷起来了! 但有的人是这样卷起来的,卷的自己都懵了。 今天,我就给偏初学者的各种问题谈谈个人刷力扣这方面的观点。 刷哪些题? 大家刷力扣,目标肯定就是为了冲击大厂的面试笔试,小部分就是为了坚持刷题保持感觉提升

bigsai 4293

PaddleOCR在医疗票据识别中的实战:从部署到业务字段提取

本文详细介绍了PaddleOCR在医疗票据识别中的实战应用,重点阐述了其离线部署方案与PP-OCRv3模型选型优势。针对医疗票据敏感数据不出本地的合规要求,文章提供了从环境搭建、模型配置到核心字段提取策略的完整流程,并分享了性能优化与系统集成的实践经验,有效解决了医疗票据自动化录入的难题。

weixin_29271053的博客 236

二叉树OJ题:LeetCode--100.相同的树

LeetCode--100.相同的树:使用C语言递归实现详细的解题过程以及递归展开图。

Yikefore的博客 854

告别里程焦虑:手把手教你用MATLAB/Simulink仿真电动车AMT换挡规律(附代码)

本文详细介绍了如何使用MATLAB/Simulink仿真电动车AMT换挡规律,帮助解决里程焦虑问题。通过搭建完整的仿真系统,包括电机MAP图处理、Stateflow逻辑实现和动力性与经济性换挡曲线生成,优化电动车换挡策略以提升续航与性能。附带的代码示例和实用技巧使开发者能够快速上手并验证仿真结果。

weixin_26757925的博客 306

力扣热题100(附刷题表版)

不仅方便查看题目,并且,在完成题目后,,我放在了结尾,大家自取,直接复制粘贴到。2. 字母异位词分组(中等)3. 最长连续序列(中等)1. 两数之和 (简单)时做记录,整理了下面。

2301_79966297的博客 2232

手把手教你用C语言给STM32写一个Modbus RTU从机库(含完整项目源码)

在工业自动化领域,Modbus RTU协议因其简单可靠的特点,成为RS485总线通信的事实标准。对于嵌入式开发者而言,为STM32等微控制器实现一个高效的Modbus RTU从机协议栈,是开发智能传感器、执行器等设备的必备技能。Modbus RTU从机的核心是一个状态机,需要处理帧接收、CRC校验、功能码解析和响应生成等环节。工业现场总会遇到意想不到的干扰情况,一个健壮的协议栈应该能够优雅地处理各种异常场景,而不是简单地崩溃或死锁。工业现场环境复杂,协议栈必须具备完善的异常处理机制。

weixin_30561425的博客 516

FLUENT Meshing Watertight Geometry工作流入门 - 4 局部加密区域

总结一下本课程中学到的内容:我们了解了如何使用模型中特定兴趣区域的BOI和FOI局部尺寸控制来加密网格。然后,了解了如何使用Box类型的局部细化区域。最后,学习了Ansys Fluent Meshing Watertight Geometry Workflow的Offset Surface类型创建局部细化区域任务。

B_etter_Man的博客 6640

100. 相同的树【 力扣(LeetCode) 】

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。【 m,n 为两棵树的结点数】【 h 为两棵树的树高】

yyh520025的博客 1257

产品缺陷检测:表面缺陷检测_(1).产品缺陷检测基础理论

确定像素之间的相似性准则,如灰度值的差异。

zhubeibei168的博客 832

leetcode hot100 中等难度 day05-刷题

leetcode hot100 中等难度 day05-刷题

weixin_46676835的博客 1142

【AI测试必学】DeepSeek API 快速入门:获取 API Key 与调用 API 步骤详解

DeepSeek API 使用与 OpenAI 兼容的格式,可以通过修改配置使用 OpenAI SDK。生成的 API Key 只会显示一次,请妥善保存。注册并登录账号,进入左侧导航栏的。创建 API Key。

blues_C的博客 1万+

雷赛控制卡的扩展IO连接

因设备的上IO点较多,所以使用了多个雷赛32点位的IO扩展卡。上位机程序在控制输出IO时发现主模块IO和第一个扩展IO的输出可以控制。但第二个IO扩展卡和第三个IO扩展卡的输出控制不了。经排查出发现轴卡在初始化时只连接了第一个扩展IO卡。增加下面的代码连接上扩展IO就可以了。雷赛控制卡的扩展IO点无法控制问题处理。

StevenChen的博客 3168

力扣刷题指南

跟着视频“手把手刷力扣”先听知识点讲解,然后把下面的经典题做了(每个系列≤4道(2easy 2medium)),接着听视频里的题目讲解。 再去刷hot100/top100,一个系列共刷10-20道 按先后顺序刷系统 争取刷200道左右 先:数组,字符串,链表,数学,栈,哈希表,图,树 后:排序,动态规划,贪心,递归,二分,双指针,深广度优先,sliding window,回溯 笔记需要记录: 思路与误区 语法:如三元表达式、最大堆 总结出的刷题模板:如union find,trie 不熟悉的知识点:.

qq_42535301的博客 4740

多周期路径约束(set_multicycle_path )

1.由慢到快的多周期约束 如下图所示,发射时钟周期是接受时钟周期的4倍。默认情况下,按照1T原则来进行静态时序分析和布局布线的。即建立时间是在发射沿后的第一个捕获沿检查,而保持时间是同一时刻下源时钟和捕获时钟的触发边沿下检查的(建立时间检查边沿的前一个触发沿)。 但是这样导致的问题就是该路径过于苛刻,为了满足这条路径的要求,不得不放弃其他路径。或者根本没办法保证这个默认的约束。总之最终造成...

Arist. 5506

刷题记录(力扣热题100)

因为构成单词的字母相同,那么将单词按同一方法排序后产生的序列一定是相同的,那么再进行哈希也一定是相同的,所以我们此时已经确定了第一维的参数,只需将第二维设置为动态数组,然后根据哈希值进行插入即可,最后遍历哈希表将其整合为一个动态数组返回即可。两个指针从两边出发,算一下当前的体积,然后更新较小的那一条边,因为每次更新x轴都会减少,如果更新长边那么体积只会变小,而更新短边才有变大的机会,然后直到两个指针相遇结束,在此期间维护最大面积即可。给定一个数组在不改变其它元素的相对顺序的情况下,将数组中的0移动到末尾。

qq_51676853的博客 2118

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

前端JavaScript力扣HOT100刷题【1-50】

注:纯手打,如有错误欢迎评论区交流!编写此文是为了更好地学习前端知识,如果损害了有关人的利益,请联系删除!本文章将不定时更新,敬请期待!!!!!

testleaf.cn 1060

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

刷题心得|这些力扣刷题经验一定不能错过

其他题目答的都差不多,算法题做不出来,拿到 offer 的概率就会下降,部分同学在刷完 1000 多道题后,发现在面试的时候 80% 的算法题都是原题。即使这道题目你做出来了,击败 100% 了,也建议去看看别人的题解,学习更多他人解题的思路,帮助自己打开脑洞,做到 一题多解。还能帮助到更多同学。是 LeetCode 精心整理的算法和数据结构专项练习,每个专项对应一个重要的知识点,并通过一系列相关的题目带大家入门,相对自己零散地选题目来说,更加简单实用,还附有讲解,是入门的不二之选。找工作刷题,登陆 👉。

weixin_44071377的博客 1325

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

上一篇: LeetCode刷题之旅(中等 -3):535. TinyURL 的加密与解密
下一篇: FAQ(89): org.jooq.exception.DataAccessException: SQL [insert into "eh_short_url"."eh_url_mapping" ("
后台技术汇
博客等级 码龄11年 670粉丝 531原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后台技术汇

对你的帮助,是对我的最好鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值