二叉树题目

二叉树常见题目

结点结构

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

1.计算节点个数

递归解法:

  1. 如果二叉树为空,节点个数为0
  2. 如果二叉树不为空,那么节点个数 = 左子树结点个数 + 右子树结点个数 + 1
int GetNodeNum(TreeNode*root){
    if(root==nullptr)
        return 0;
    return GetNodeNum(root->left)+GetNodeNum(root->right)+1;
}

2.求二叉树深度

  1. 如果二叉树为空,二叉树的深度为0
  2. 如果二叉树不为空,二叉树的深度 = max (左子树深度,右子树深度) + 1
int GetDepth(TreeNode*root){
    if(root==nullptr)
        return 0;
    int depleft  = GetDepth(root->left);
    int depright = GetDepth(root->right);
    return max(depleft ,depright ) + 1;
}

3.将二叉查找树转换成双向链表

TreeNode*Convert(TreeNode*root){
    if(root==nullptr)
        return nullptr;
    if(root->left==nullptr&&root->right==nullptr)
        return root;
    TreeNode *left = Convert(root->left);//这里是为了找到左子树最左边的叶子结点
    TreeNode* cur = left;
    while(cur!=nullptr&&cur->right!=nullptr){
        cur = cur->right;
    }
    if(left!=nullptr){//在刚开始的时候这个curr==left
        curr->next = root;
        root->left = curr;
    }
    Treenode*right = Convert(root->right);
    if(right!=nullptr)
    {
        right->left = root;
        root->right = right;
    }
    return left!=nullptr ?left :root;
    //返回的总是最左边的位置,如果左边为空返回根结点,否则返回左边结点
}

4.求二叉树第k层节点个数

递归解法:

  1. 如果二叉树为空或者k<1返回0;
  2. 如果二叉树不为空并且k==1,返回1
  3. 如果二叉树不为空并且k>1,返回左子树中k-1层的节点个数+右子树k-1层节点个数之和
int GetNodeNumKthLevel(TreeNode*root,int k){
    if(root==nullptr||k<1)
        return 0;
    if(k==1)
        return 0;
    int numleft = GetNodeNumKthLevel(root->left,k-1);
    int numright = GetNodeNumKthLevel(root->right,k-1);
    return (numleft +numright );
    //返回的是左边结点个数+右边结点个数
}

5.求二叉树中叶子结点个数

1.如果二叉树为空,返回0
2.如果二叉树不为空,左右子树为空返回1
3.如果二叉树不为空,左右子树不为空,返回左边结点个数+右边结点个数

int GetLeafNodeNum(TreeNode*root){
    if(root==nullptr)
        return 0;
    if(root->left==nullptr&&root->right==nullptr)
        return 1;
    int numleft= GetLeafNodeNum(root->left);
    int numright= GetLeafNodeNum(root->right);
    return (numleft+numright);
}

6.判断两棵二叉树是否结构相同

首先搞清楚,结构相同;并不代表结点内的数据相同
/*空 空
空 不空
不空 空
不空 不空 :继续判断*/
1. 如果两根二叉树都为空,返回真
2. 如果两棵二叉树,一个空,另一个不空,返回假
3. 如果两棵二叉树都不为空,如果对应的左子树和右子树结构相同,返回真,其它返回假

bool Structcmp(TreeNode*root1,TreeNode*root2){
    if(root1==nullptr&&root2==nullptr)
        return true;
    else if(root1==nullptr || root2==nullptr)
        return false;
    bool resultleft = Structcmp(root1->left,root2->left);
    bool resultright = Structcmp(root1->right,root2->right);
    return (resultleft &&resultright );
}

7.判断二叉树是不是平衡二叉树

int treedepth(TreeNode*root)
    {
        if (root == nullptr)
            return 0;
        int left = treedepth(root->left);
        int right = treedepth(root->right);
        return (left > right) ? (left + 1) : (right + 1);
        //return max(left,right) + 1;
    }
    bool Isbalanced_tree(TreeNode*root){
        if (root == nullptr)
            return true;//如果二叉树结点为空返回真
        int left = treedepth(root->left);
        int right = treedepth(root->right);
        if (abs(left - right) > 1)
            return false;//如果高度差大于1为假
        //此处返回的是递归判断,左右子树是否为平衡二叉树
        return Isbalanced_tree(root->left) && Isbalanced_tree(root->right);
    }

8.求二叉树的镜像

TreeNode*mirror(TreeNode*root)
{
    if (!root)
        return nullptr;
    TreeNode*p_left = mirror(root->left);
    //只要不停的调用就会出现栈
    TreeNode*p_right = mirror(root->right);
    root->left = p_right;
    root->right = p_left;
    return root;//如果子为空,返回空。否则返回根节点
}
/*
    一左一右交换左右子树,然后交换其指向,深度递归
*/

9.求二叉树的最小深度

int mini_depth(TreeNode*root)
{
    if (!root)
        return 0;//直接判断左右子结点,是否存在然后根据此进行返回
    if (!root->left)//求出左子树的高度
        return mini_depth(root->left) + 1;//左边子树高度
    if (!root->right)//求出右子树的高度
        return mini_depth(root->right) +1;//右子树高度
    return min(mini_depth(root->left), mini_depth(root->right)) + 1;
    //返回左右子树中较小的那个高度
}

10.判断二叉树是不是完全二叉树

如果二叉树的深度为h,除第h层外,其它(1~h-1)的结点数都达到最大个数,第h层所有的结点都连续集中在最左边,这就是完全二叉树。
按层遍历二叉树,当遇到第一个结点的左子树为空时,则该结点左右子树必须为空,而且此结点后的结点左右子树必须为空,否则不是完全二叉树

bool isCompleteBinary_tree(TreeNode*root)
{
    if (root == nullptr)
        return false;
    queue<TreeNode*> q;
    q.push(root);
    bool hasnochild = false;
    bool result = true;
    while (!q.empty()){
        TreeNode* pnode = q.front();
        q.pop();
        if (hasnochild){
            if (pnode->left != nullptr || pnode->right != nullptr){
                result = false;
                break;
            }
        }
        else
        {
            if (pnode->left != nullptr&&pnode->right != nullptr){
                q.push(pnode->left);
                q.push(pnode->right);
            }
            else if (pnode->left != nullptr&&pnode->right == nullptr){
                hasnochild = true;
                q.push(pnode->left);
            }
            else if (pnode->left == nullptr&&pnode->right != nullptr){
                result = false;
                break;
            }
            else
            {//此处指当左右都为空的时候
                hasnochild = true;
            }
        }
    }
    return result;
}

11.求二叉树中两个结点的最低公共祖先结点

求最低公共结点,采用深度递归从头结点到包含此结点的路径,然后遍历到开始变化的那个结点的位置就是最低公共祖先
注意:
1. 如果两个结点分别在根节点的左右子树中,则返回根节点
2. 如果两个结点都在左子树,则递归处理左子树;如果两个结点都在右子树,则递归处理右子树

bool GetNodePath(TreeNode*root, TreeNode*pNode, vector<TreeNode*>&path){
        if (root == pNode) //路径作为传入传出参数
        {
            path.push_back(root);
            return true;
        }
        if (root == nullptr)
            return false;
/*这里是先进行的判断,然后在存入容器的操作,如果先直接压入容器那么就应该有回退的操作
 递归结束条件,当一直没找到,为空的时候直接返回,当找到了压入容器,改变标记位置,返回*/
        path.push_back(root);
        bool found = false;
        found = GetNodePath(root->left, pNode, path);
        //采用先序遍历,先把根节点存储然后往下判断
        if (!found)//如果左边没找到,递归查找右子树
            found = GetNodePath(root->right, pNode, path);
        if (!found)
            path.pop_back();
    //这里是右子树操作,如果没找到要回退,然后进行操作
        return found;
    }
    TreeNode* Find_commonnode(TreeNode*root, TreeNode*pNode1, TreeNode*pNode2){
        if (root == nullptr || pNode1 == nullptr || pNode2 == nullptr)
            return nullptr;
        vector<TreeNode*>path1;
        bool result1 = GetNodePath(root, pNode1, path1);
        vector<TreeNode*>path2;
        bool result2 = GetNodePath(root, pNode2, path2);
        if (!result1 || !result2)
            return nullptr;
        TreeNode*plast = nullptr;
        vector<TreeNode*>::const_iterator iter1 = path1.begin();
        vector<TreeNode*>::const_iterator iter2 = path2.begin();
        while (iter1 != path1.end() && iter2 != path2.end())
        {
            if (*iter1 == *iter2)
                plast = *iter1;//将结点的内容存储起来
            else      
                break;
            iter1++;
            iter2++;
        }
        return plast;
    }

12.求二叉树中距离最远的结点之间的距离

递归解法:
1.如果二叉树为空返回0,一种方式是包含此结点,计算左右子树的最大深度
2.不包含此结点,计算左有子树中最大的距离,然后从三者之间计算求出最大值

    int GetMaxDistance(TreeNode*root)
    {
        if (root == nullptr)
            return 0;
        int res = depth(root->left)+depth(root->right);
        return max(res, max(GetMaxDistance(root->left), GetMaxDistance(root->right)));
    }
    int depth(TreeNode*root){
        if (root == nullptr)
            return 0;
        return max(depth(root->left),depth(root->right)) + 1;
    }

猜你喜欢

转载自blog.csdn.net/alpha_love/article/details/78006895