LeetCode 101. 对称二叉树 思考分析

题目

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

1

/
2 2
/ \ /
3 4 4 3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

1

/
2 2
\
3 3

进阶:
你可以运用递归和迭代两种方法解决这个问题吗?

思路一,超时

层序遍历,然后如果该结点是空结点,往该层子数组中填0,否则填val;
当此层所有结点都被遍历了(包括空结点),观察子数组是否对称。
然后更新queue,如果该结点为空结点,则它的子结点也是空结点,如果该结点不是空结点,它的子结点根据真实情况填,如果为空也填入NULL。
不过这样好像超时了,也就无法验证了。
退出循环的条件是,该层的所有结点都是空结点

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:bool isSymmetric(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);while(1){//该层结点元素个数 = 该层队列元素int size = que.size();vector<int> vec;int null_times=0;//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列for(int i =0;i<size;i++){TreeNode* node = que.front();//将队首元素送入该层结果que.pop();if(node!=NULL) {vec.push_back(node->val);//将左右孩子结点入队列,作为下一层的元素if(node->left!=NULL) que.push(node->left);else que.push(NULL);if(node->right!=NULL) que.push(node->right);else que.push(NULL);}else{null_times++;vec.push_back(-2147483648);//将左右孩子结点入队列,作为下一层的元素que.push(NULL);que.push(NULL);} }if(null_times == size) break;int vecsize=vec.size();for(int j=0;j<vecsize/2+1;j++){if(vec[j]!=vec[vecsize-1-j]) return false;}}return true;}
};

思路二,构造翻转二叉树,判断是否相同

先构造一棵反转二叉树,然后按顺序遍历这两棵树,判断是否相同。
Leetcode226. 翻转二叉树(递归、迭代、层序三种解法)
LeetCode 100. 相同的树 思考分析
不过此处有一个问题,我们当时翻转二叉树的操作是在输入的二叉树上进行修改的。这样如果直接isSameTree(root,invertTree(root));
得到的结果都是true。所以我们需要先深复制一个新的二叉树,然后在新的二叉树上完成翻转操作,然后将翻转后的二叉树与原本的二叉树进行判断。
关于深复制一棵二叉树:
LintCode 375. 克隆二叉树(深复制)

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:TreeNode* invertTree(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);while(!que.empty()){int size = que.size();for(int i =0;i<size;i++){TreeNode* node = que.front();que.pop();TreeNode* tmp;tmp = node->left;node->left = node->right;node->right = tmp;//将左右孩子结点入队列,作为下一层的元素if(node->left) que.push(node->left);if(node->right) que.push(node->right);}}return root;}bool isSameTree(TreeNode* p, TreeNode* q) {if(p && q){if(p->val == q->val){return isSameTree(p->right,q->right) && isSameTree(p->left,q->left);}else{return false;} }else if(!p && !q){return true;}return false;}TreeNode * preorder(TreeNode * root){if(root==NULL) return NULL;TreeNode * ans;ans=new TreeNode(root->val);if(root->left!=NULL){ans->left=preorder(root->left);}if(root->right!=NULL){ans->right=preorder(root->right);}return ans;}bool isSymmetric(TreeNode* root) {TreeNode *roota;roota=preorder(root);return isSameTree(root,invertTree(roota));}
};

在这里插入图片描述

参考其他思路

之前的构造的思路会导致空间严重浪费,并且时间耗费也较多。
关于二叉树是否对称,我们要比较的是根结点的左子树与右子树是不是相互翻转的。递归遍历的时候要同时遍历两棵树,比较两棵子树的里侧和外侧元素是否相同
本题的遍历顺序为后序遍历,因为要通过递归函数的返回值来判断两个子树的内测结点与外侧结点是否相等。
一棵树遍历顺序为左右中,另一棵树遍历顺序是右左中。这里可以理解为一种回溯的思想。

递归法

1、确定递归地参数和返回值
参数:该结点的左子树结点、右子树结点
返回值:bool类型
bool compare(TreeNode* left,TreeNode* right)
2、确定终止条件
1、左右都为空,返回true
2、左右只有一个为空,返回false
3、左右结点均不为空,比较结点数值,不相同返回false
4、左右结点均不为空,数值相同返回true

if(left == NULL && right==NULL) return true;
else if(left!=NULL && right==NULL) return false;
else if(right!=NULL && left==NULL) return false;
else if(left->val != right->val) return false;

3、确定单层递归逻辑
处理左右结点皆不为空且数值相同的情况。
1、比较二叉树外侧是否对称:传入左结点的左孩子,右结点的右孩子。
2、比较内侧是否对称,传入左结点的右孩子,右结点的左孩子。
3、如果左右都对称就返回true,否则返回false

bool outside = compare(left->left,right->right);	
bool inside = compare(left->right,right->left);
bool isSame = outside && inside;		
return isSame

完整代码

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:bool compare(TreeNode* left,TreeNode* right){if(left == NULL && right==NULL) return true;else if(left!=NULL && right==NULL) return false;else if(right!=NULL && left==NULL) return false;else if(left->val != right->val) return false;bool outside = compare(left->left,right->right);	bool inside = compare(left->right,right->left);bool isSame = outside && inside;		return isSame;}bool isSymmetric(TreeNode* root) {if(root == NULL) return true;return compare(root->left,root->right);}
};

在这里插入图片描述

迭代法

这一题的本质是判断两个树是否相互翻转,并非简单的遍历。这里可以使用队列来比较两个树(根结点的左右子树)是否相互翻转。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:bool isSymmetric(TreeNode* root) {if(root == NULL) return true;queue<TreeNode*> que;que.push(root->left);       //将左子树头结点加入队列que.push(root->right);      //将右子树头结点加入队列while(!que.empty())         //判断两个树是否翻转{TreeNode* leftNode = que.front();que.pop();TreeNode* rightNode = que.front();que.pop();if(!leftNode && !rightNode) {//左右结点均为空,说明此时是对称的continue;}//左右一个结点不为空,或者都不为空但是数值不同,返回falseif((!leftNode || !rightNode || (leftNode->val!=rightNode->val))){return false;}//外侧que.push(leftNode->left);   //左左que.push(rightNode->right); //右右//内侧que.push(leftNode->right);que.push(rightNode->left);}return true;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378018.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

直方图反向投影

通过直方图反向投影&#xff0c;根据目标衣服颜色的特征来进行定位 cv2.calcHist([roi_hsv],[0,1],None,[32,48],[0,180,0,256])其中[32,48]表示bin的个数&#xff0c;可以修改&#xff0c;当然范围越小越精确 import cv2 import numpy as np from matplotlib import pyplot …

LeetCode 二叉树、N叉树的最大深度与最小深度(递归解)

目录104. 二叉树的最大深度559. N叉树的最大深度111. 二叉树的最小深度之前的笔记中&#xff0c;已经用层序遍历解决过这个问题了现在试着用深度的解法去求解104. 二叉树的最大深度 给定一个二叉树&#xff0c;找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径…

十、模板匹配

一、概念 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。 需要首先给定一个模板图像A&#xff0c;和一个待检测图像B。 在待检测图像B上&#xff0c;从左往右&#xff0c;从上往下计算待检测图像B和模板图像A所重叠的匹配度&#xff0c;匹配度越高则两者相同的可…

基于WF的意见征集4(浅析)

接口项目&#xff1a;IClass&#xff08;项目名称&#xff09; HTHuiFuusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Workflow.Runtime;using System.Workflow.Activities;namespace IClass{ /// <summary> /…

那些VisualStudio隐藏的调试功能

VisualStudio是一个强大的调试工具&#xff0c;里面很多隐藏功能少有人问津&#xff0c;但是在特定场景可以节省你很多时间&#xff0c;本文主要介绍一些VisualStudio调试相关的隐藏功能&#xff0c;欢迎大家补充。 运行到指针(Run to cursor) 大多数人用Visual Studio在调试程…

十一、图像二值化

一、二值图像 其实就是把图像转换为只有黑白的两种颜色图像&#xff0c;即像素值非零即一 三角阈值二值化 对一个图像进行操作&#xff0c;获取图像的直方图&#xff0c;找到波峰和波谷进行连线设为线段A&#xff0c;每个点做有关线段A的垂线垂足在线段A上&#xff0c;最后将…

地毯店 如何辨别地毯的好坏?

在实地选购地毯品牌时&#xff0c;许多地方需要引起注意&#xff0c;而且要显得专业&#xff0c;这样才能科学深入地辨别地毯的好坏。比如&#xff0c;辨明拉绞地毯和抽绞地毯两种工艺的打结方法几乎相同&#xff0c;只是变绞形式上有所区别。抽绞的方式较古老&#xff0c;一般…

十二、图像金字塔

一、原理 reduce高斯模糊降采样 expand扩大卷积 PyrDown&#xff1a;降采样 PyrUp&#xff1a;还原 二、高斯金字塔 import cv2 import numpy as np from matplotlib import pyplot as pltdef pyramid(image):level 3temp image.copy()pyramid_image []for i in range(le…

LeetCode 110. 平衡二叉树思考分析

题目 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 示例 1: 给定二叉树 [3,9,20,null,null,15,7] 3 / 9 20 / 15 7 返回 true 。 示例 2…

十三、图像梯度

一、两种算子 一阶导数—Sobel算子 水平梯度&#xff1a; 垂直梯度&#xff1a; 最终图像梯度&#xff1a; 二阶导数—Laplacian算子 在二阶导数的时候&#xff0c;最大变化处的值为零&#xff0c;即边缘是零值。 常见的拉普拉斯算子&#xff1a;、其所有元素之和为零。…

LeetCode 257. 二叉树的所有路径 思考分析

目录题目思路一&#xff1a;深度递归思路二&#xff1a;广度迭代关于回溯题目 给定一个二叉树&#xff0c;返回所有从根节点到叶子节点的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 输入: 输出: [“1->2->5”, “1->3”] 解释: 所有根节点到叶子节点的路…

十四、Canny边缘提取

一、算法步骤 1&#xff0c;对图像进行GaussianBlur(高斯模糊)消除一些噪声 2&#xff0c;对图像进行灰度转换cvtColor 3&#xff0c;计算梯度Sobel/Scharr 4&#xff0c;非最大信号抑制 5&#xff0c;高低阈值输出二值图像 设定两个阈值T1和T2&#xff0c;凡是高于T2的都保…

图解PCB布线数字地、模拟地、电源地,单点接地抗干扰!

我们在进行pcb布线时总会面临一块板上有两种、三种地的情况&#xff0c;傻瓜式的做法当然是不管三七二十一&#xff0c;只要是地 就整块敷铜了。这种对于低速板或者对干扰不敏感的板子来讲还是没问题的&#xff0c;否则可能导致板子就没法正常工作了。当然若碰到一块板子上有多…

十五、霍夫直线检测

一、自定义 import cv2 import numpy as np from matplotlib import pyplot as pltdef line_detection(image):gray cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)edges cv2.Canny(gray,50,150,apertureSize3)lines cv2.HoughLines(edges,1,np.pi/180,200)for line in lines:rho…

【C++ grammar】对象指针、对象数组、函数参数

目录1、Object Pointer & Dynamic Object1. Accessing Object Members via Pointers2. Creating Dynamic Objects on Heap2、Array of Objects声明方式3、Passing Objects to Functions1、Objects as Function Arguments (对象作为函数参数)2. Objects as Function Return …

十六、霍夫圆形检测

一、获取圆形检测原理 原图如下&#xff1a; 选取一个圆的任意点设定为圆形进行绘制圆形&#xff0c;交与一点 再将平面直角坐标系上的各点&#xff0c;通过公式转到极坐标上 很明显的看出较亮的点为圆心&#xff0c;然后通过半径进行绘制出圆。 二、实现步骤 由于霍夫圆检…

商务智能与交易系统的区别

商务智能与交易系统的区别 1、系统设计的区别 商务智能与交易系统之间的差异主要体现在系统设计和数据类型上&#xff08;见表 1.1 和表1.2&#xff09;。交易系统把结构强加于商务之上&#xff0c;不管谁来进行一项交易活动&#xff0c; 都会遵循同样的程序和规则&#xff0c;…

LeetCode 572. 另一个树的子树 思考分析

题目 给定两个非空二叉树 s 和 t&#xff0c;检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。 示例 1: 给定的树 s: 示例 2: 给定的树 s: 思路 思路&#xff1a;首先层序遍历s树…

十七、轮廓发现

一、轮廓发现原理 轮廓发现是在图像边缘提取的基础上寻找对象轮廓的方法&#xff0c;故边缘提取的阈值的选定会影响到最终轮廓发现的结果。 其本质是基于二值图像的&#xff0c;边缘提取常用Canny进行提取边缘 轮廓发现也是基于拓扑结构&#xff0c;扫描连通图&#xff0c;最后…

关于 WebRequest.RegisterPrefix

RegisterPrefix 方法将 WebRequest 子代注册到服务请求。 WebRequest 后代通常被注册来处理特定的协议&#xff08;例如 HTTP 或 FTP&#xff09;&#xff0c;但也可能被注册来处理对特定服务器或服务器上的路径的请求。 已注册的预注册保留类型包括下列类型&#xff1a; htt…