【leetcode】101.对称二叉树

文章目录


碎碎念

周末这两天偷偷划水了咳咳,不过终于是进城吃上心心念念的寿司郎嘻嘻嘻。昨天本来是想来上工的但突然就电池急速掉电整个人无力了,遂在家充电。对了,昨天还第一次尝试去俱乐部打那种拼场的羽毛球,很爽啊很爽啊,感觉大家都很厉害!!我得规划一下泡图书馆and打球and锻炼减肥的时间了,这个假期一定要很充实!


一、题目


二、思路和题解

1.思路

原本想的是像层序遍历那样一层一层来,左子树的就入栈,右子树的就出栈,一旦发现有不对的就直接false,否则遍历完了就true。但是那个时候还没学会层序遍历,遂放弃。

后面又想到,前面做过翻转二叉树,如果把左子树先翻转到右子树那边,然后再和原来的右子树去作比较,只要有不一样的地方就出错。这个方案应该可行,不过当时主播沉迷于递归且觉得这个方案效率很低,也没细想。

(我错了放过我这一次吧下次一定不偷懒了TT)

于是到递归!!既然是递归,那我们就要考虑递归函数怎么写了。以下思考步骤详细请见代码随想录

首先第一步,确认递归函数的参数和返回值 。这里我们因为是对树进行递归,且主要是判断是否对称,不需要有其他数组啊数啊来记录某一个结果什么的,所以参数就是root;返回值也很好理解了,就是true和false。

然后是确定终止条件。这里我们需要分情况讨论。因为我们是判断一个二叉树是否对称,所以就不能只是单纯的比较左孩子和右孩子是否相等,这个只能在根节点的时候是有用的,再往下就不能这么做了。那要看下面的是否对称,我们要对比的就是L.left和R.right(假设L指向左节点,R指向右节点)。这里又可以再分情况来讨论我们的终止条件了:

  1. 当两个指针都跨过叶子节点指向null,此时返回true:
  2. 当其中一个指针指向节点而另一个指针已经跨过叶子节点指向null,说明不对称,返回false:
  3. 当两个节点的值不相等,说明不对称,返回false:

因为题目条件里有指明节点数至少是一个,因此不用考虑空树情况。以上,包含了终止条件的所有情况。

最后一步是确定单层递归逻辑。这里其实我们在上一步已经有分析了,也就是如果当前节点是root,对比L和R是否相等;如果当前节点不是root,对比L.left和R.right是否相等以及对比L.right和R.left是否相等,只要有不相等即不对称。

2.代码(递归)

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        return check(root->left,root->right);
    }
    bool check(TreeNode* p,TreeNode* q){
        // 两个都跨过叶子节点指向null
        if (!p&&!q){
            return true;
        }
        // 不是上面的情况,说明至少有一个非空,此时存在一个空/两个节点的值不相等说明不对称
        if (!p||!q||p->val!=q->val){
            return false;
        }
        //要求 L.left节点的值等于R.right节点的值 且 L.right节点的值等于R.left节点的值 才对称
        return check(p->left,q->right)&&check(p->right,q->left);
    }
};

算法的时间复杂度是 O(n),因为要遍历 n 个节点

空间复杂度是 O(n),空间复杂度是递归的深度,也就是跟树高度有关,最坏情况下树变成一个链表结构,高度是n。

三、其他解法(迭代)

题解里除了递归还有迭代的做法,学习学习。
参考题解在这里,迭代和递归都有清晰的图解,推荐!

我们用队列来实现,思路如下:

  1. 先将根节点的左右孩子都放进队列中(特殊)
  2. 一次取两个节点来比较值是否相等
  3. 将left节点的左孩子和right节点的右孩子放入队列中
  4. 将left节点的右孩子和right节点的左孩子放入队列中
  5. 重复2-4步骤,直到队列为空或发现不对称

以下是java实现的算法。(复制粘贴题解的

java 复制代码
class Solution {
	public boolean isSymmetric(TreeNode root) {
		if(root==null || (root.left==null && root.right==null)) {
			return true;
		}
		//用队列保存节点
		LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
		//将根节点的左右孩子放到队列中
		queue.add(root.left);
		queue.add(root.right);
		while(queue.size()>0) {
			//从队列中取出两个节点,再比较这两个节点
			TreeNode left = queue.removeFirst();
			TreeNode right = queue.removeFirst();
			//如果两个节点都为空就继续循环,两者有一个为空就返回false
			if(left==null && right==null) {
				continue;
			}
			if(left==null || right==null) {
				return false;
			}
			if(left.val!=right.val) {
				return false;
			}
			//将左节点的左孩子, 右节点的右孩子放入队列
			queue.add(left.left);
			queue.add(right.right);
			//将左节点的右孩子,右节点的左孩子放入队列
			queue.add(left.right);
			queue.add(right.left);
		}
		
		return true;
	}
}

时间复杂度是 O(n),空间复杂度是 O(n)。

四、错误回顾

递归思路没想明白,以为直接对比左右孩子。

相关推荐
寻寻觅觅☆8 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
fpcc8 小时前
并行编程实战——CUDA编程的Parallel Task类型
c++·cuda
偷吃的耗子8 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
化学在逃硬闯CS9 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
ceclar1239 小时前
C++使用format
开发语言·c++·算法
Gofarlic_OMS10 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
lanhuazui1010 小时前
C++ 中什么时候用::(作用域解析运算符)
c++
charlee4410 小时前
从零实现一个生产级 RAG 语义搜索系统:C++ + ONNX + FAISS 实战
c++·faiss·onnx·rag·语义搜索
夏鹏今天学习了吗10 小时前
【LeetCode热题100(100/100)】数据流的中位数
算法·leetcode·职场和发展
老约家的可汗10 小时前
初识C++
开发语言·c++