【精选高频面试题】 2w字硬肝-二叉树属性

二叉树属性

Leetcode.101.对称二叉树

101. 对称二叉树 - 力扣(LeetCode) (leetcode-cn.com)

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

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

进阶:

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

思路

递归思路:首先我们如何确定这个二叉树对称,就是它的左右子树对称(外侧值等于外侧值,内侧值等于内侧值)。接下来就是写出递归函数,抓住递归函数三要素:返回类型与参数【我们比较的是两个节点所以我们传入的是节点,返回的就是bool值】;终止条件【在比较的时候我们要先排除空节点的情况,有3中情况:右空,左空,双空。在排除一种清空,双有,且值不相等】;单层循环逻辑【接下来就是递归的主要逻辑,我们在递归函数中,继续比较左节点的右节点与右节点的左节点,右节点的右节点与左节点的左节点的大小】

class Solution {
public:
    bool compare(TreeNode* left,TreeNode* right){
        if(left&&right&&(left->val!=right->val))return false;
        else if(!left&&right)return false;
        else if(left&&!right)return false;
        else if(!left&!right)return true;
        else compare(left->left,right->right)&&compare(left->right&&right->left);
    }
    bool isSymmetric(TreeNode* root) {
         if(root==nullptr)return true;
         return compare(root->left,root->right);
    }
};

迭代思路:

我们将两个节点的值放入队列进行判断比较

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
         queue<TreeNode*>que;
         if(root==NULL)return true;
         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;
             }
             if(!leftnode||!rightnode||(leftnode->val!=rightn->val)){
                 return false;
             }
             que.push(leftnode->left);
             que.push(rightnode->right);
             que.push(leftnode->right);
             que.push(rightnode->left);
         }
        return true;
    }
};

Leetcode.100.相同的树

给你两棵二叉树的根节点 pq ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

实例一:

输入:p = [1,2,3], q = [1,2,3]
输出:true

实例二:

输入:p = [1,2], q = [1,null,2]
输出:false

c++源码

class Solution {
public:
    bool compare(TreeNode*root1,TreeNode*root2){
        if(root1==nullptr&&root2!=nullptr)return false;
        else if(root1!=nullptr&&root2==nullptr)return false;
        else if(root1==nullptr&&root2==nullptr)return true;
        else if(root1!=nullptr&&root2!=nullptr&&(root1->val!=root2->val))return false;
        else {
            return compare(root1->left,root2->left)&&compare(root1->right,root2->right);
        }
    }
    bool isSameTree(TreeNode* p, TreeNode* q) {
           return compare(p,q);
    }
};

Leetcode.572.另一个树的子树

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false
//实现代码:
class Solution {
public:
    bool compare(TreeNode*r,TreeNode*s){
        if(r==nullptr&&s!=nullptr)return false;
        else if(r!=nullptr&&s==nullptr)return false;
        else if(r==nullptr&&s==nullptr)return true;
        else if(r!=nullptr&&s!=nullptr&&(r->val!=s->val))return false;
       
        bool bo1=compare(r->left,s->left);
        bool bo2=compare(r->right,s->right);
        bool com=bo1&&bo2;
        return com;
    }
    bool isSubtree(TreeNode* root, TreeNode* subRoot) {    
     if(root==nullptr)return false;
     if(subRoot==nullptr)return true;
     return compare(root,subRoot)||isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
    }
};

Leetcode.104.二叉树的最大深度

104. 二叉树的最大深度 - 力扣(LeetCode) (leetcode-cn.com)

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

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

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

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

3

/
9 20
/
15 7
返回它的最大深度 3 。

思路:在[上一篇文章]((10条消息) 【精选高频面试题】二叉树遍历合集_Sefr后端-CSDN博客)中我们用到了迭代法-层序遍历的方式来求得其最大深度。因为层数=深度。在这篇文章中我们使用递归法。

class Solution {
public:
    int getdepth(TreeNode*root){
        if(root==nullptr)return 0;
        int leftdepth=getdepth(root->left);
        int rightdepth=getdepth(root->right);
        int depth=1+max(leftdepth,rightdepth);
        return depth;
    }
    int maxDepth(TreeNode* root) {
         int depth=getdepth(root);
         return depth;
    }
};

递归法:

class Solution {
public:
    int maxDepth(TreeNode* root) {
         queue<TreeNode*>que;
         int count=0;
         if(root!=nullptr)que.push(root);
         while(!que.empty()){
             int size=que.size();
             for(int i=0;i<size;i++){
                 TreeNode*node=que.front();
                 que.pop();
                 if(node->left)que.push(node->left);
                 if(node->right)que.push(node->right);

             }
            count+=1;
         }
         return count;
    }
};

Leetcode.559.N叉树的最大深度

559. N 叉树的最大深度 - 力扣(LeetCode) (leetcode-cn.com)

给定一个 N 叉树,找到其最大深度。

最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。

N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。

输入:root = [1,null,3,2,4,null,5,6]
输出:3
//思路一:迭代法-层序遍历
class Solution{
    public:
           int maxDepth(Node* root){
               queue<Node*>que;
               if(root!=NULL)que.push(root);
               int depth=0;
               while(!que.empty()){
                   int size=que.size();
                   depth++;
                   for(int i=0;i<size;i++){
                       Node* node=que.front();
                       que.pop();
                       for(int j=0;j<node->children.szie();j++){
                           if(node->children[j])que.push(node->children[j]);
                       }
                   }
               }
               return depth;
           }
};
//递归法
class Solution{
    int maxDepth(Node*root){
        if(root==0)return 0;
        int depth=0;
        for(int i=0;i<root->children.size();i++){
           depth=max(depth,maxDepth(root->children[i]));
        }
        
    }
};

Leetcode.111.二叉树的最小深度

111. 二叉树的最小深度 - 力扣(LeetCode) (leetcode-cn.com)

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

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

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

输入:root = [3,9,20,null,null,15,7]
输出:2
//迭代法-层序遍历
class Solution {
public:
    int minDepth(TreeNode* root) {
          queue<TreeNode*>que;
          if(root!=nullptr)que.push(root);
          int mindepth=0;
          while(!que.empty()){
              int size=que.size();
              mindepth++;
              for(int i=0;i<size;i++){
                  TreeNode*node=que.front();
                  que.pop();
                  if(node->left)que.push(node->left);
                  if(node->right)que.push(node->right);
                  if(!node->left&&!node->right)return mindepth;
              }
          }
          return mindepth;
    }
};
//`递归法
class Solution {
public:
    int getdepth(TreeNode*root){
        if(root==nullptr)return 0;
        int leftdepth=getdepth(root->left);
        int rightdepth=getdepth(root->right);
        if(root->right!=nullptr&&root->left==nullptr){
            return  1+rightdepth;
        }
        if(root->right==nullptr&&root->left!=nullptr){
            return 1+leftdepth;
        }//排除根节点的左节点或者右节点为空的情况。
        int result=1+min(leftdepth,rightdepth);
        return result;
    }
    int minDepth(TreeNode* root) {
         int mindepth=0;
         mindepth=getdepth(root);
         return mindepth;
    }
};

Leetcode.222.完全二叉树节点个数

222. 完全二叉树的节点个数 - 力扣(LeetCode) (leetcode-cn.com)

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例 1:

输入:root = [1,2,3,4,5,6]
输出:6

思路:普通二叉树做法(层序遍历+递归),完全二叉树做法(2^树深度-1)

做法一:层序遍历

class Solution {
public:
    int countNodes(TreeNode* root) {
          queue<TreeNode*>que;
          if(root!=nullptr)que.push(root);
          int number=0;
          while(!que.empty()){
              int size=que.size();
              for(int i=0;i<size;i++){
                  TreeNode*node=que.front();
                  que.pop();
                  number++;
                  if(node->left)que.push(node->left);
                  if(node->right)que.push(node->right);
              }
          }
          return number;
    }
};

做法二:递归

class Solution {
public:
    int countNodes(TreeNode* root) {
        if(root==nullptr)return 0;
        int numbers=0;
        int leftnumber=countNodes(root->left);
        int rightnumber=countNodes(root->right);
        numbers=1+rightnumber+leftnumber;
        return numbers;
    }
};

做法三:完全二叉树的性质

class Solution {
public:
    int countNodes(TreeNode* root) {
          if(root==nullptr)return 0;
          TreeNode*left=root->left;
          TreeNode*right=root->right;
          int leftheight=0,rightheight=0;
          while(left){
              left=left->left;
              leftheight++;
          }
          while(right){
              right=right->right;
              rightheight++;
          }
          if(rightheight==leftheight){
              return (2<<leftheight)-1;
          }
          return countNodes(root->left)+countNodes(root->right)+1;
    }
};

Leetcode.110.平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

输入:root = [3,9,20,null,null,15,7]
输出:true

输入:root = [1,2,2,3,3,null,null,4,4]
输出:false

思路:这道题我们采用后序(左右中)的递归来解决。

第一:首先我们思考递归函数的返回值类型与参数类型:我们要获取这个节点的左右节点的高度来比较,所以我们返回int.参数类型为节点类型

第二:终止条件:什么时候停止递归?当节点为空的时候我们结束递归,也就是遍历到叶子节点的时候。

第三:单层遍历逻辑:我们要实现高度平衡,所以,| 左节点的高度-右节点的高度 |>1.当发生这种情况的时候我们就直接返回-1.表示这棵树不是平衡二叉树了。

class Solution {
public:
    int depth(TreeNode*root){
        if(root==NULL)return 0;
        int leftdepth=depth(root->left);
        if(leftdepth==-1)return -1;
        int rightdepth=depth(root->right);
        if(rightdepth==-1)return -1;
        if(abs(leftdepth-rightdepth)>1){
            return -1;
        }
        else{
            return 1+max(leftdepth,rightdepth);
        }
    }
    bool isBalanced(TreeNode* root) {
        return  depth(root)==-1?false:true;
    }
};
class Solution {
public:
        void trval(TreeNode*cur,vector<int>&path,vector<string>&res){
           path.push_back(cur->val);
           if(cur->left==nullptr&&cur->right==nullptr){
               string Spath;
               for(int i=0;i<path.size()-1;i++){
                   
                   Spath+=to_string(path[i]);
                   Spath+="->";
               }
               Spath+=to_string(path[path.size()-1]);
               res.push_back(Spath);
               return;
           }
           while(cur->left){
               trval(cur->left,path,res);
               path.pop_back();
           }
           while(cur->right){
               trval(cur->right,path,res);
               path.pop_back();
           }
        }   
        vector<string> binaryTreePaths(TreeNode* root) {
           vector<string>res;
           vector<int>path;
           if(root==nullptr)return res;
           trval(root,path,res);
           return res;

    }
};

Leetcode.257.二叉树的所有路径

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

示例 1:

输入:root = [1,2,3,null,5]
输出:["1->2->5","1->3"]

思路:这道题因为要记录从上往下的路径所以我们要采用前序的递归法,同时使用了回溯的方法。

第一:确定返回类型以及参数。因为我们是要保存路径,所以不需要返回任何值->void;我们要设置一个vector来保存数值,同时用来回溯(pop_back())以及一个vector来保存结果.同时传入一个树节点

void  traval(TreeNode* cur,vector<int>path,vector<string>result)

第二:终止条件:当我们的cur的左右节点都为空的时候那么就该终止,终止的逻辑就是把path中的内容转化为string保存到结果容器中

if(cur->left==NULL&&cur->right==NULL){
    string Spath;
    for(int i=0;i<path.size()-1;i++){
        Spth+=to_string(path[i]);
        spth+="->";
    }
    Spth+=to_string(path[path.size()-1]);
    result.push_back(Spth);
    return;
}

第三:单层遍历逻辑:因为要前序遍历我们要先处理中间的节点,添加进path.

path.push_back(cur->val)中

如果cur的左或者右节点存在的话,我们就继续往下迭代,直到不为空,同时我们要回溯

if(cur->left){
    traval(cur->left,path,result);
    path.pop_back();//回溯
}
if(cur->right){
    traval(cur->left,path,result);
    path.pop_back();//回溯
}

本题完整代码

class Solution {
public:
        void trval(TreeNode*cur,vector<int>&path,vector<string>&res){
           path.push_back(cur->val);//将根节点要先插入进去
           if(cur->left==nullptr&&cur->right==nullptr){
               string Spath;
               for(int i=0;i<path.size()-1;i++){
                   
                   Spath+=to_string(path[i]);
                   Spath+="->";
               }
               Spath+=to_string(path[path.size()-1]);
               res.push_back(Spath);
               return;
           }
           if(cur->left){
               trval(cur->left,path,res);
               path.pop_back();
           }
           if(cur->right){
               trval(cur->right,path,res);
               path.pop_back();
           }
        }   
        vector<string> binaryTreePaths(TreeNode* root) {
           vector<string>res;
           vector<int>path;
           if(root==nullptr)return res;
           trval(root,path,res);
           return res;

    }
};

Leetcode.404.左叶子节点之和

计算给定二叉树的所有左叶子之和。

示例:

​ 3

/
9 20
/
15 7

在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

思路:本题采用前序迭代法和递归法。

//前序迭代法
class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        stack<TreeNode*>st;
        if(root==NULL)return 0;
        st.push(root);
        int result=0;
        while(!st.empty()){
          TreeNode*node=st.top();
            st.pop();
            if(root->left!=NULL&&root->left->left==NULL&&root->left->right==NULL){
                result+=root->left->val;
            }
            if(root->left)st.push(root->left);
            if(root->right)st.push(root->right);
        }
        return result;
    }
};
class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
       if(root==NULL)return 0;
        int leftvalue=sumOfLeftLeaves(root->left);
        int rightvalue=sumOfLeftLeaves(root->right);
        int midvalue=0;
        if(root->left!=NULL&&root->left->left==NULL&&root->left->right==NULL){
            midvalue=root->left->val;
        }
        int sum=leftvalue+rightvalue+mvalue;
        return sum;
    }
};

Leetcode.513.找树左下角的值

513. 找树左下角的值 - 力扣(LeetCode) (leetcode-cn.com)

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

输入: root = [2,1,3]
输出: 1

思路一:这道题采用层序遍历比较好理解,遍历到每一层,记录一下每一层的第一个节点的值即可。

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
       queue<TreeNode*>que;
        if(root!=NULL)que.push(root);
        int result=0;
        while(!que.empty()){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode*node=que.front();
                que.pop();
                if(i==0){
                    result=node->val;
                }
                if(node->left)que.push(node->left);
                if(node->right)que.push(node->right);
            }
        }
        return result;
    }
};

思路二:递归。由于我们不知道该叶子节点是不是最大深度的叶子节点,所以我们需要回溯。

第一:返回类型与参数类型:我们首先需要设置两个全局变量,记录最大深度与最大深度的最左叶子节点值,每次遇到这个节点我们就更新一下最大深度值与最大深度,所以返回类型为void 参数类型为节点与最大深度

第二:终止条件:当我们遇到左叶子节点的时候我们就停止下来记录

第三:单层遍历逻辑:我们需要继续遍历这个节点的左节点和右节点,并同时回溯

class Solution {
public:
    int maxleftlen=INT_MIN;
    int maxleftvalue=0;
    void leva(TreeNode*root,int lenmax){
        if(root->left==NULL&&root->right==NULL){
            if(lenmax>maxleftlen){
                maxleftlen=lenmax;
                maxleftvalue=root->val;
            }
            return ;
        }
        if(root->left){
            lenmax++;
            leva(root->left,lenmax);
            lenmax--;
        }
        if(root->right){
            lenmax++;
            leva(root->right,lenmax);
            lenmax--;
        }
        return;
    }
    int findBottomLeftValue(TreeNode* root) {
        leva(root,0);
        return maxleftvalue;
    }
};

Leetcode.112.路径总和

112. 路径总和 - 力扣(LeetCode) (leetcode-cn.com)

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum ,判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。

叶子节点 是指没有子节点的节点。

示例 1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true

**思路:**这道题我们使用递归法

第一:类型:我们需要判断是否存在这样的一条路径,且不需要搜索整棵二叉树,则需要返回值bool;

​ 参数:如果我们对遍历的节点的值进行相加,则会比较复杂,要记录下来值,所以我们逆向思考,设置一个计数器,每次遇到一个节点我们就减去这个值,当计数器为0时就返回结果。所以我们参数为节点和一个计数器

第二:终止条件:当我们遍历到叶子节点的时候,且计数器为0的时候,就返回true;当遍历到叶子节点的时候,且计数器不为0,那么返回false;

第三:单层遍历逻辑:我们继续遍历root左右节点

class Solution {
public:
    bool trval(TreeNode*root,int count){
        if(!root->left&&!root->right&&count==0){
            return true;
        }
        if(!root->left&&!root->right){
            return false;
        }
        if(root->left){
            if(trval(root->left,count-root->left->val))//回溯
            return true;//如果找到了这个路径理解返回
        }
        if(root->right){
           if(trval(root->right,count-root->right->val))//回溯
            return true;
        }
        return false;
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
       if(root==NULL)return false;
       return trval(root,targetSum-root->val);
        
    }
};

Leetcode.113.路径总和Ⅱ

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。

这道题是要遍历整棵树所以不需要返回类型

class Solution {
public:
    vector<int>path;//记录路径
    vector<vector<int>>res;//记录结果
    void trval(TreeNode*root,int count){
        if(!root->left&&!root->right&&count==0){
            res.push_back(path);
        }
        if(!root->left&&!root->right){
            return;
        }
         if(root->left){
            path.push_back(root->left->val);
            trval(root->left,count-root->left->val);//回溯
            path.pop_back(); //回溯
         }
         if(root->right){
             path.push_back(root->right->val);
             trval(root->right,count-root->right->val);//回溯
             path.pop_back();//回溯
         }
        return ;
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
         path.clear();
         res.clear();
         if(root==NULL)return res;
         path.push_back(root->val);
         trval(root,targetSum-root->val);
         return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值