代码随想录算法训练营第15天-leetcode-二叉树3:110.平衡二叉树;404.左叶子之和;513.找树左下角的值;222.完全二叉树的节点个数

ps:路径题和左下角的值做题顺序反了!

110.平衡二叉树

力扣题目链接(opens new window)

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

本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

示例 1:

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

分析:

  • 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。——先序
  • 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。——后序

递归三部曲:

1、返回值:返回高度,但如果左右高度已经相差1了,已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了

2、终止条件:r==null,return 0

3、单层递归逻辑:分别求左右两边高度,作差。如果两边高度差>1,则返回-1,表示已经不是平衡二叉树了;如果高度差<=1,则返回该结点的真实高度=左右两边高度较大的那个+1

注意**

返回-1:同时具备返回正常情况int,和返回正常or非正常状态 bool的能力

int getheight(struct TreeNode*r){
    if(r==NULL) return 0;
    int h1=getheight(r->left);
    int h2=getheight(r->right);
    if(h1==-1 || h2==-1) return -1;
    int h=abs(h1-h2);
    if(h>1) return -1;
    return fmax(h1,h2)+1;
}

bool isBalanced(struct TreeNode* root) {
    int h=getheight(root);
    if(h==-1) return false;
    return true;
}

404.左叶子之和

力扣题目链接(opens new window)

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

分析:

左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点

递归三要素:

1、返回值:root以下左叶子之和

传入值:因为需要父结点,才能判断左孩子是否为左叶子,故而传入root,查找root->left是否符合条件

2、递归终止条件:root=null,return 0;

**然而注意到,当左孩子为左叶子时,仍然应遍历右子树,右子树中也会有左叶子

3、单层递归逻辑:

当遇到左叶子节点的时候,记录数值。

然后通过递归求取左子树左叶子之和,和 右子树左叶子之和。

return 相加便是整个树的左叶子之和。

int sumOfLeftLeaves(struct TreeNode* root){
    int h1;
    if(root==NULL) return 0;

    if(root->left!=NULL && root->left->left==NULL && root->left->right==NULL){
        h1=root->left->val;
    }
    else {h1=sumOfLeftLeaves(root->left);}//求左子树中左叶子的和

    int h2=sumOfLeftLeaves(root->right);//求右子树中左叶子之和
    return h1+h2;//返回root结点往下,左叶子之和

}

 

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

力扣题目链接(opens new window)

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

示例 1:

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

示例 2:

  • 输入:root = []
  • 输出:0

示例 3:

  • 输入:root = [1]
  • 输出:1

 1、遍历所有的节点

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

 2、层序遍历

3、利用完全二叉树性质简化

分析:判断左右子树是不是满二叉树

——是:用2^h -1的方式算左右子树的节点个数,求和,得到父结点

——不是:继续往下走

——【在完全二叉树的前提下】满二叉树:往最左遍历和往最右遍历深度是一样的

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

int countNodes(struct TreeNode* root) {
    if(root==NULL ) return 0;
    int h=getheight(root, 1);
    if(h==getheight(root, 0)){
        return pow(2,h)-1;
    }
    return countNodes(root->left)+countNodes(root->right)+1;
}

 

513.找树左下角的值

力扣题目链接(opens new window)

给定一个二叉树,在树的最后一行找到最左边的值。

**注意:

1、在while/if中定义的内容,不能在while/if外使用——因为有可能根本没能进入while/if

2、函数要修改输入值时:

设计函数时:f(*a)

调用函数时:f(&a)

1、层序遍历

int findBottomLeftValue(struct TreeNode* root) {
    struct TreeNode**queue=(struct TreeNode**)malloc(sizeof(struct TreeNode*)*50000);
    int front=-1,rear=-1;
    int answer;

    queue[++rear]=root;

    while(front!=rear){
        int last=rear-front;
        int j=0;
        
        while(j<last){
            struct TreeNode* pop_tree=queue[++front];
            if(j==0) answer=pop_tree->val;
            if(pop_tree->left!=NULL) queue[++rear]=pop_tree->left;
            if(pop_tree->right!=NULL) queue[++rear]=pop_tree->right;

            j++;
        }
    }
    return answer;
}

 2、递归方法

无所谓使用前中后序的哪一种,因为父结点不需要进行修改或者实现相应的操作

!!出现深度更深的结点,则把curval curheight对应修改,height是维护当前节点的高度的

void dfs(struct TreeNode*root,int height,int *curval,int*curheight){
    //curval 和 curheight都是要返回的,故而写成int*的形式
    if(root==NULL) return;
    height++;
    dfs(root->left,height,curval,curheight);
    dfs(root->right,height,curval,curheight);
    if(height>*curheight){
        *curheight=height;
        *curval=root->val;
    }

}
int findBottomLeftValue(struct TreeNode* root) {
    int curval,curheight=0;
    dfs(root,0,&curval,&curheight);
    return curval;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值