力扣刷题笔记(9)

emmm,不刷树的题目还真以为自己有多了解树。。。题目一做,方纸上得来终觉浅啊,才知道自己的浅薄和学海的浩瀚。

那,我们来看看这次遇到些什么问题

前情概要

在做树相关题目时,我觉得基础还是要先牢靠一点的:
二叉树的前中后序遍历


题目(1):探寻树的深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


题目(2):验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
示例 1:

输入:
    2
   / \
  1   3
输出: true

示例 2:

输入:
    5
   / \
  1   4
     / \
    3   6
输出: false

解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/validate-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


题目(3):验证对称树

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

例如,二叉树 [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

进阶:

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

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/symmetric-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


我的题解(1)

这题实在简单的不想说什么了,连流程图我都不想画,直接上代码吧。

int maxDepth(TreeNode* root) {
        if(root == NULL)
            return 0;
        return 1 + max(maxDepth(root->left), maxDepth(root->right));
    }

简单吧,三行代码的事情。。。
或者说,一行代码的事情而已。。。


我的题解(2)

这题真的打破了我对树的幻想。我一直以为二叉搜索树我还挺熟的,没想到,居然处处碰壁。。。

刚开始我采用层序遍历的方式,一层层比对,(当前节点小于当前右节点,大于左节点),但是很快就发现问题了。

在这里插入图片描述

如果觉得上面的那个方式没错,那么看完这张图就不会这么想了吧。

当时看到这个情况,我也是整个人都不好了,不仅仅要和子节点比对,孙子节点还要防着。。。

经过一早上的挣扎,我放弃了前序遍历,果然是我基础不牢,这个模型其实可以用中序遍历来弄,可惜我就浪费了几个小时没想到。

对一颗正常的二叉搜索树,用中序遍历打印出来的节点顺序是严格从一端到另一端的。

当时也想着直接取值比对,但终究是递归也不太熟,最后只好把值都放到数组里在遍历数组比对了。

struct TreeNode {
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

bool MidOrderTraverse(TreeNode* T, vector<int>& temp)
{
	if (T == NULL)
		return true;

	MidOrderTraverse(T->left,temp);	

	temp.push_back(T->val);
	cout << T->val << " ";
	MidOrderTraverse(T->right,temp);	

	for (int i = 0; i < temp.size()-1; i++)
	{
		int j = i + 1;
		if (temp[i] >= temp[j])
			return false;
	}
	return true;
}

bool isValidBST(TreeNode* T)
{
	vector<int> temp;
	int k = MidOrderTraverse(T, temp);
	return k;
}

最后就做成这个样子了。


我的题解(3)

经过第二题,我对递归又深入了解了一点,知道该把一些希望固定住的值固定住,可以用参数形式,也可以用static.

那这题其实就很简单了,只要把树从根节点左右对半开,然后比较左右两颗子树就好,比较子树的话,前中后序都可以,不过需要做一点小改变:

我用的是正反前序遍历同步的方法

int Pre(TreeNode* Tl, TreeNode* Tr,int flag)	//flag为标志退出循环
{
	if (flag == 0)
		return false;

	if (Tl == NULL)
	{
		if(Tr == NULL)
			return true;
		return false;
	}
	if (Tr == NULL)
		return false;
		
	if (Tl->val != Tr->val)
	{
		flag = 0;
		return false;
	}
	
	flag = Pre(Tl->left,Tr->right,flag);
	if (flag == 0)
		return false;

	flag = Pre(Tl->right,Tr->left,flag);
	if (flag == 0)
		return false;
	return true;
}

bool isSymmetric(TreeNode* root)
{

	//先排除极端情况
	if (root == NULL)
		return true;
	if (root->left == NULL)
	{
		if (root->right != NULL)
			return false;
		return true;
	}
	if (root->right == NULL)
		return false;

	if (root->left->val != root->right->val)
		return false;

	int ret = Pre(root->left, root->right,1);

	return ret;
}

看着挺多的,其实四分之三的篇幅都用在了对特殊情况的剔除上。真正匹配的代码是这里:

int Pre(TreeNode* Tl, TreeNode* Tr,int flag)	//flag为标志退出循环
{
	if (flag == 0)
		return false;

	flag = Pre(Tl->left,Tr->right,flag);
	if (flag == 0)
		return false;

	flag = Pre(Tl->right,Tr->left,flag);
	if (flag == 0)
		return false;
	return true;
}

官方题解(1)略

官方题解(2)

方法一: 递归

上述思路可以用递归法实现。首先将结点的值与上界和下界(如果有)比较。然后,对左子树和右子树递归进行该过程。

在这里插入图片描述

class Solution {
  public boolean helper(TreeNode node, Integer lower, Integer upper) {
    if (node == null) return true;

    int val = node.val;
    if (lower != null && val <= lower) return false;
    if (upper != null && val >= upper) return false;

    if (! helper(node.right, val, upper)) return false;
    if (! helper(node.left, lower, val)) return false;
    return true;
  }

  public boolean isValidBST(TreeNode root) {
    return helper(root, null, null);
  }
}

> 作者:LeetCode
> 链接:https://leetcode-cn.com/problems/validate-binary-search-tree/solution/yan-zheng-er-cha-sou-suo-shu-by-leetcode/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

复杂度分析

时间复杂度 : O(N)。每个结点访问一次。
空间复杂度 : O(N)。我们跟进了整棵树。


官方题解(3)

和我的差不多,迭代的就不说了。


总结

树!!!
我也不多说,心照不宣

原创文章 153 获赞 719 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_43762191/article/details/105888668
今日推荐