草庐IT

LeetCode刷题 —— 手撕二叉树

命由己造~ 2023-04-08 原文

题目目录

1.单值二叉树

思路:
1️⃣如果节点为空,就不用判断,返回true
2️⃣如果节点不为空,则判断他的左右子节点的值,只要不同,就返回false,相同就继续递归(走到最后会返回true

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


bool isUnivalTree(struct TreeNode* root){
    if(root == NULL)
    {
        return true;
    }
    if(root->left)
    {
        if(root->val != root->left->val)
        {
            return false;
        }
    }
    if(root->right)
    {
        if(root->val != root->right->val)
        {
            return false;
        }
    }
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

递归发现不同的时候(不管是左还是右)返回false,而最后又是&&关系,所以只要有不同就返回false

流程图:


2.二叉树的最大深度

思路:
这颗树的层数等于左右子树层数大的那个加1,慢慢递归下去,
1️⃣是空就返回0
2️⃣是叶子节点就返回1

很容易写出代码:

*     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


int maxDepth(struct TreeNode* root){
    if(root == NULL)
    {
        return 0;
    }
    if(root->left == NULL && root->right == NULL)
    {
        return 1;
    }
    return maxDepth(root->left) > maxDepth(root->right) ? 
    maxDepth(root->left) + 1 : maxDepth(root->right) + 1 ;
}

但是这种代码会超出时间限制,原因是判断左右子树层数时会递归两遍,后面+1时又要递归一遍,所以我们可以用变量先存取来,比较完就返回大的那个。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int maxDepth(struct TreeNode* root){
    if(root == NULL)
    {
        return 0;
    }
    if(root->left == NULL && root->right == NULL)
    {
        return 1;
    }
    int left = maxDepth(root->left);
    int right = maxDepth(root->right);
    return left > right ? left + 1 : right + 1;
}

流程图:


3.二叉树的前序遍历

这道题首先要知道有多少个节点,前序遍历存到数组,要考虑到递归时临时变量不会影响递归前的,所以要传指针变量

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


/**
 * Note: The returned array must be malloced, assume caller calls free().
 */


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

void _preorderTraversal(struct TreeNode* root, int* a, int* k)
{
    if(root == NULL)
    {
        return;
    }
    a[(*k)++] = root->val;
    _preorderTraversal(root->left, a, k);
    _preorderTraversal(root->right, a, k);
}


int* preorderTraversal(struct TreeNode* root, int* returnSize){
    int size = TreeSize(root);
    int* arr = (int*)malloc(sizeof(int) * size);
    int a = 0;
    _preorderTraversal(root, arr, &a);
    *returnSize = size;
    return arr;
}

4.翻转二叉树

思路:
从根节点往下递归,如果递归到当前节点root时root的左右子树都已经翻转,那么直接交换左右子树的位置。所以大思想时后序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */



struct TreeNode* invertTree(struct TreeNode* root){
    if(root == NULL)
    {
        return NULL;
    }
    struct TreeNode* left = invertTree(root->left);
    struct TreeNode* right = invertTree(root->right);
    root->left = right;
    root->right = left;
    return root;
}

流程图:


5.相同的树

这道题比较简单,当同时到NULL的时候就返回true,中间只要有不相同就返回false

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


bool isSameTree(struct TreeNode* p, struct 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);
}

图跟第二题一样


6.对称二叉树

思路:
如果是空树,就返回true,不是的话就像判断相同树那道题一样,分成两个树往下递归

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


bool _isSymmetric(struct TreeNode* left, struct TreeNode* right)
{
    if(left == NULL && right == NULL)
    {
        return true;
    }
    if(left == NULL || right == NULL)
    {
        return false;
    }
    if(left->val != right->val)
    {
        return false;
    }
    return _isSymmetric(left->left, right->right) && _isSymmetric(left->right , right->left);
}




bool isSymmetric(struct TreeNode* root){
    if(root == NULL)
    {
        return true;
    }
    return _isSymmetric(root->left, root->right);
}

这道题也是上面翻转二叉树和相同的树两道题结合,先翻转再判断是否相同


7.另一棵树的子树

思路:
遍历所有节点,判断root树的每个节点是否是subroot的子树,如果都没有则返回false,只要有就返回true 所以用 ||

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


bool _isSubtree(struct TreeNode* p, struct TreeNode* q)
{
    if(p == NULL && q == NULL)
    {
        return true;
    }
    if(p == NULL || q == NULL)
    {
        return false;
    }
    if(p->val != q->val)
    {
        return false;
    }
    return _isSubtree(p->left, q->left) && _isSubtree(p->right, q->right);
}


bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
    //遍历root所有节点比较
    //没有则false
    if(root == NULL)
    {
        return false;
    }
    if(_isSubtree(root, subRoot))
    {
        return true;
    }
    return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

8.平衡二叉树❗️❗️

这道题可以用上面求最大深度的题求,把每个节点的左右子树深度差都算一下,只要有>1的就false

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


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


bool isBalanced(struct TreeNode* root){
    if(root == NULL)
    {
        return true;
    }
    if(abs(maxDepth(root->left) - maxDepth(root->right)) > 1)
    {
        return false;
    }
    return isBalanced(root->left) && isBalanced(root->right);
}

但是我们来看看他的时间复杂度

递归的时间复杂度就是递归次数
isBalanced递归次数:N
每次递归次数:N + N / 2 + N / 2 + N / 4 + N / 4 + N / 4 + N / 4……(假设是满二叉树)
所以总体是O(N^2)

要求优化到O(N)

8.1时间复杂度优化

先搞清楚为什么复杂度会高?

判断平衡时会算左右子树的高度,而从上往下递归下面的高度会重复计算,那么我没让你可以用后序遍历从下往上计算,就不会有重复

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


bool _isBalanced(struct TreeNode* root, int* ph)
{
    if(root == NULL)
    {
        *ph = 0;
        return true;
    }
    int lefthight = 0;
    if(!_isBalanced(root->left, &lefthight))
    {
        return false;
    }
    int righthight = 0;
    if(!_isBalanced(root->right, &righthight))
    {
        return false;
    }
    *ph = lefthight > righthight ? lefthight + 1 : righthight + 1;
    return abs(lefthight - righthight) < 2;
}



bool isBalanced(struct TreeNode* root){
    int hight = 0;
    return _isBalanced(root, &hight);
}

有关LeetCode刷题 —— 手撕二叉树的更多相关文章

  1. Python 刷Leetcode题库,顺带学英语单词(31) - 2

    ValidPalindromeGivenastring,determineifitisapalindrome,consideringonlyalphanumericcharactersandignoringcases. [#125]Example:"Aman,aplan,acanal:Panama"isapalindrome."raceacar"isnotapalindrome.Haveyouconsiderthatthestringmightbeempty?Thisisagoodquestiontoaskduringaninterview.Forthepurposeofthisproblem

  2. ruby - 在 Ruby 中实现二叉树 - 2

    我一直在尝试在Ruby中实现BinaryTree类,但我得到了stackleveltoodeep错误,尽管我似乎没有在该特定代码段中使用任何递归:1.classBinaryTree2.includeEnumerable3.4.attr_accessor:value5.6.definitialize(value=nil)7.@value=value8.@left=BinaryTree.new#stackleveltoodeephere9.@right=BinaryTree.new#andhere10.end11.12.defempty?13.(self.value==nil)?true:

  3. IDEA使用LeetCode插件 - 2

    前言我们习惯用idea编写、调试代码,在LeetCode上刷题时,如果能够在IDEA编写代码,并且做好代码管理,是一件事半功倍的事情。对于后续复习题目,做笔记也会非常便利。本文目的在于介绍LeetCodeEditor的使用,以及配置工具类,最终目录结构如下:note:放置笔记src:放置代码leetcode.editor.cn:插件LeetCodeEditor自动生成utils:自定义的工具包,可用于自动化输入测试用例,定义题目需要的类(结构体)out:运行测试时自动生成LeetCodeEditorGitHub:https://github.com/shuzijun/leetcode-edit

  4. 【JavaScript】手撕前端面试题:对象参数浅拷贝 | 简易深拷贝 | 完整深拷贝 - 2

    🖥️NodeJS专栏:Node.js从入门到精通🖥️博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)🖥️TypeScript知识总结:TypeScript从入门到精通(十万字超详细知识点总结)🧑‍💼个人简介:大三学生,一个不甘平庸的平凡人🍬👉你的一键三连是我更新的最大动力❤️!文章目录1、浅拷贝要求思路代码2、简易深拷贝要求思路代码3、完整深拷贝要求思路代码1、浅拷贝要求补全JavaScript代码,要求实现一个对象参数的浅拷贝并返回拷贝之后的新对象。注意:参数可能包含函数、正则、日期、ES6新对象是对对象的参数进行浅拷贝,并不是直接对整个对象进行浅拷贝(整个

  5. LeetCode——2347. 最好的扑克手牌 - 2

    一、题目给你一个整数数组ranks和一个字符数组suit。你有5张扑克牌,第i张牌大小为ranks[i],花色为suits[i]。下述是从好到坏你可能持有的手牌类型:“Flush”:同花,五张相同花色的扑克牌。“ThreeofaKind”:三条,有3张大小相同的扑克牌。“Pair”:对子,两张大小一样的扑克牌。“HighCard”:高牌,五张大小互不相同的扑克牌。请你返回一个字符串,表示给定的5张牌中,你能组成的最好手牌类型。注意:返回的字符串大小写需与题目描述相同。来源:力扣(LeetCode)链接:https://leetcode.cn/problems/best-poker-hand/d

  6. 面试总结+力扣第二天刷题 - 2

    一.面试总结    4月20号下午进行了一场大数据视频面试,总结一下踩坑点:    1.确定面试后,第一件事要和HR确定面试方式,具体时间、地点、什么软件、岗位JD等必须信息。        这里很多人有一个思想误区,认为问的太多会给HR不好的印象;其实大可不必,如果你通过了简历筛选,你就有权力使用公司招聘的人力资源。    2.要在面试10分钟前就进入面试的环境中,以防突发事件。    3.面试最开始都会有一个自我介绍环节,这个自我介绍环节,一定要慎之又慎,最好写下来,让朋友、长辈等审核多遍。    注:我面试时,在这踩了一个坑,自我介绍的时候踩了我要面试的岗位一脚,被技术面试官抓住了这一点

  7. LeetCode:344. 反转字符串 - 2

    🍎道阻且长,行则将至。🍓🌻算法,不如说它是一种思考方式🍀算法专栏:👉🏻123一、🌱344.反转字符串题目描述:编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间解决这一问题。来源:力扣(LeetCode)难度:简单提示:1s[i]都是ASCII码表中的可打印字符示例1:输入:s=[“h”,“e”,“l”,“l”,“o”]输出:[“o”,“l”,“l”,“e”,“h”]示例2:输入:s=[“H”,“a”,“n”,“n”,“a”,“h”]输出:[“h”,“a”,“n”,“n”,“a”,“H”

  8. 【日常系列】LeetCode《28·动态规划3》 - 2

    数据规模->时间复杂度10^8内容二维数组中的路径问题买卖股票的最佳时机lc62【剑指098】【top100】:不同路径https://leetcode.cn/problems/unique-paths/提示:1题目数据保证答案小于等于2*10^9#方案一:dfs+记忆化classSolution:defuniquePaths(self,m:int,n:int)->int:memo=[[-1]*nfor_inrange(m)]defdfs(i,j):ifi==m-1andj==n-1:return1ifi>=morj>=n:return0ifmemo[i][j]!=-1:returnmemo[

  9. javascript - 与二维碰撞有关的四叉树 - 2

    我一直在研究这个:https://github.com/mikechambers/ExamplesByMesh/blob/master/JavaScript/QuadTree/src/QuadTree.js我相信我理解四叉树的一般概念,尽管我对它们的工作原理和上面的实现有两个问题:难道你不需要每隔几毫秒重建整个树吗?在Javascript中,这不会非常慢吗?如果我有这样的东西:http://davzy.com/screenshots/skitched-20120318-180324.png,那么很容易找到同一个四边形中的其他点,但我有一个矩形与3个不同的四边形相交,有没有办法让它显示为

  10. LeetCode:454. 四数相加 II —— 哈希表为什么叫哈希表~ - 2

    🍎道阻且长,行则将至。🍓🌻算法,不如说它是一种思考方式🍀算法专栏:👉🏻123hash是什么,哈希表为什么叫哈希表?一、🌱454.四数相加II题目描述:给你四个整数数组nums1、nums2、nums3和nums4,数组长度都是n,请你计算有多少个元组(i,j,k,l)能满足:0nums1[i]+nums2[j]+nums3[k]+nums4[l]==0来源:力扣(LeetCode)难度:中等提示:n==nums1.lengthn==nums2.lengthn==nums3.lengthn==nums4.length1-2^28示例1:输入:nums1=[1,2],nums2=[-2,-1],n

随机推荐