代码随想录Day16 | 104二叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数

代码随想录Day16 | 104二叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数

  • 二叉树的最大深度
  • 二叉树的最小深度
  • 完全二叉树的节点个数

二叉树的最大深度

文档讲解:代码随想录
视频讲解:
状态: 之前用层序遍历解决了,这次学习迭代方法

求解过程中,采用的是前序还是后序的遍历主要看最终结果的处理逻辑,因为我们处理逻辑一般都是放在中节点上进行的,即判断这一个节点目前的深度。
而本题可以使用后序的原因就在于其是根节点,根节点的高度和深度相等。我们来观测后序求高度的代码

int left = getheight(cur->left);
int right = getheight(cur->right);
int mid = 1+max(left,right);

中节点的高度是由左节点和右节点高度来计算的
我们再来看前序遍历,就是直接求深度的过程,原理就是每到达左节点或者右节点深度+1,在递归中我们需要传入这个深度作为参数,这个深度相当于就是计数器,记录当前另一个参数就是节点所在的层数。

//前序
int mid = 0;//mid为返回结果,不能每层更新为0,每层使用dep更新
//中节点
mid = dep > mid ? dep : mid;
//左节点
if(cur->left)
{
	//此时说明深度需要加1 ,
	dep++;
	getdepth(cur->left,dep);//以当前层的左节点为中节点开始迭代
	//回溯,因为这个操作是在中节点位置
	dep--;
}if(cur->right)
{
	//此时说明深度需要加1 ,
	dep++;
	getdepth(cur->right,dep);//以当前层的右节点为中节点开始迭代
	//回溯,因为这个操作是在中节点位置
	dep--;
}

除了递归中需要改变深度,其他操作都相当于在同一层操作,需要保持深度的不变性。

二叉树的最小深度

文档讲解:代码随想录
视频讲解:
状态:同样之前用层序遍历

层序遍历就是要注意跳出循环的时机,每层循环都++,然后当左节点和右节点都为空时,再++然后return 这个值。

class Solution {
public:
    int minDepth(TreeNode* root) {
        queue treeque;
        if(root) treeque.push(root);
        int count = 0;
        while(!treeque.empty())
        {
            int tempsize = treeque.size();
            for(int i=0;ileft == nullptr&&cur->right == nullptr) return count+1;
                if(cur->left) treeque.push(cur->left);
                if(cur->right) treeque.push(cur->right);
            }
            count++;
        }
        return count;
    }
};

递归:要注意只有左右节点都是空的时候,才能说明该节点是叶子节点,如果左节点为空右节点不为空,那么最小深度应该是1+右节点的迭代。

class Solution {
public:
    int getHeight(TreeNode* root)
    {
        if(root == nullptr) return 0;
        int left = getHeight(root->left);
        int right = getHeight(root->right);

        //当left null right不为Null时
        if(root->left == nullptr && root->right != nullptr)
        {
            return 1+right;
        }
        if(root->right == nullptr && root->left != nullptr)
        {
            return 1+left;
        }

        return 1+min(left ,right);
    }

public:
    int minDepth(TreeNode* root) {
        return getHeight(root);
    }
};

完全二叉树的节点个数

文档讲解:代码随想录
视频讲解:
状态

递归,记录每一个左节点和右节点,迭代的变化量就是节点个数而不是节点深度了。

class Solution {
public:
    int getNum(TreeNode* root)
    {
        if(root == nullptr) return 0;
        //左节点的子树中节点的个数
        int left = getNum(root->left);
        //右节点的子树中节点的个数
        int right = getNum(root->right);
        //中节点的节点个数计算,1表示中节点
        int mid = 1+left+right;
        return mid;
    }
public:
    int countNodes(TreeNode* root) {
        return getNum(root);
    }
};

利用完全二叉树的特性,所有子树都可以划分为满二叉树和不满的完全二叉树,对于满二叉树那就是从父节点开始一直只遍历左节点和只遍历右节点,如果长度相等那说明是满的,此时节点个数就是 2 n − 1 2^n-1 2n1,如果是不满的,那么就继续递归直到最后为满二叉树,一个节点的二叉树也是满的。

/**
 * 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:
    int getNum(TreeNode* root)
    {
        //终止条件
        //1.root == nullptr
        if(root == nullptr) return 0;
        //2. 遍历左节点个数和右节点个数相等,即这个子树是满二叉树
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        int leftlen = 0;
        int rightlen = 0;
        while(left)
        {
            leftlen++;
            left = left->left;
        }
        while(right)
        {
            rightlen++;
            right = right->right;
        }
        if(leftlen == rightlen)
        {
            return (2<left);
        int rightnode = getNum(root->right);
        int mid = 1+leftnode+rightnode;
        return mid;
    }
public:
    int countNodes(TreeNode* root) {
        return getNum(root);
    }
};

时间复杂度:相当于二分法,首先假设二叉树节点为n,那么对每个左节点或者右节点递归调用时间复杂度为 O ( l o g n ) O(log n) O(logn),而对每个左节点或者右节点有需要遍历其子树的左节点和右节点 O ( l o g n ) O(log n) O(logn),所以总时间复杂度就是 O ( l o g 2 n ) O(log^2n) O(log2n)

你可能感兴趣的:(算法)