leetcode树与二叉树练习

​ 此篇博客用于记录leetcode树与二叉树部分刷题记录及题解,不定期更新~

二叉树基本函数

引论.leetcode二叉树定义

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

树的遍历方式总体分为两类深度优先搜索(DFS)、广度优先搜索(BFS);

  • 常见的 DFS : 先序遍历、中序遍历、后序遍历

  • 常见的 BFS : 层序遍历(即按层遍历)

105.二叉树的最大深度

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

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

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

	3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

使用递归

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

543.二叉树的直径

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

示例 :给定二叉树

      1
     / \
    2   3
   / \     
  4   5    

返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

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

236.二叉树的最近公共祖先

1.题目描述

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例 :

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。

2.题解

根据以上定义,若 root是 p, q 的 最近公共祖先 ,则只可能为以下情况之一:

​ p和 q 在 root的子树中,且分列 root的 异侧(即分别在左、右子树中);
​ p = root,且 q 在 root 的左或右子树中;
​ q = root,且 p 在 root 的左或右子树中;

struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q){
    //终止条件
    if(root==NULL||root==p||root==q){
        return root;
    }
    //递归过程
    struct TreeNode*left=lowestCommonAncestor(root->left,p,q);
    struct TreeNode*right=lowestCommonAncestor(root->right,p,q);
    //单次操作
    if(left==NULL){
        return right;
    }
    if(right==NULL){
        return left;
    }
    //返回值
    return root;//当左右均不为空时,说明这个结点就是它们的最近公共祖先
}

3.复杂度分析:

时间复杂度 O(N) : 其中 N 为二叉树节点数;最差情况下(树退化为链表时),需要递归遍历树的所有节点。
空间复杂度 O(N) : 最差情况下,递归深度达到 N ,系统使用 O(N) 大小的额外空间。

二叉树的遍历

引论.模板语法

while( 栈非空 || p 非空)
{
if( p 非空)
{

}
else
{

}
}

144.二叉树的前序遍历

1.递归

void preorder(struct TreeNode* root,int* returnSize,int *res)/*中序遍历二叉树*/
{
   if(root==NULL) return;
   res[(*returnSize)++]=root->val;
   preorder(root->left,returnSize,res);
   preorder(root->right,returnSize,res);

}
int size(struct TreeNode* root)/*求二叉树数据个数*/
{
   if(!root) return 0;
   return size(root->left)+size(root->right)+1;
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    int treesize=size(root);
    int *res=(int *)malloc(sizeof(int)*treesize);
    *returnSize=0;
    preorder(root,returnSize,res);
    return res;
}

2.非递归

int* preorderTraversal(struct TreeNode* root, int* returnSize){
    struct TreeNode **stack=(struct TreeNode**)malloc(sizeof(struct TreeNode*)*1000);
    int *res=(int*)malloc(sizeof(int)*10000);
    int i=0,top=0;
    struct TreeNode *p=NULL;
    stack[0]=root;
    while(top!=-1){
        p=stack[top];
        top--;//pop
        while(p){
            res[i++]=p->val;
            if(p->right){
                stack[++top]=p->right;//push
            }
            p=p->left;
        }
    }
    *returnSize=i;
    return res;
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    struct TreeNode **stack=(struct TreeNode**)malloc(sizeof(struct TreeNode*)*1000);
    int *res=(int*)malloc(sizeof(int)*10000);
    int top=-1;
    *returnSize=0;
    struct TreeNode *p=root;
    while(p!=NULL || top!=-1){
       if(p){
           stack[++top]=p;
           res[(*returnSize)++]=p->val;
           p=p->left;
       }else{
           p=stack[top--];
           p=p->right;
       }
    }
    return res;
}

94.二叉树中序遍历

1.递归

void inorder(struct TreeNode* root,int* returnSize,int *res)/*中序遍历二叉树*/
{
   if(root==NULL) return;
   inorder(root->left,returnSize,res);
   res[(*returnSize)++]=root->val;
   inorder(root->right,returnSize,res);

}
int size(struct TreeNode* root)/*求二叉树数据个数*/
{
   if(!root) return 0;
   return size(root->left)+size(root->right)+1;
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
    int treesize=size(root);
    int *res=(int *)malloc(sizeof(int)*treesize);
    *returnSize=0;
    inorder(root,returnSize,res);
    return res;
}

2.非递归

int* inorderTraversal(struct TreeNode* root, int* returnSize){
    struct TreeNode **stack=(struct TreeNode**)malloc(sizeof(struct TreeNode*)*1000);
    int *res=(int*)malloc(sizeof(int)*10000);
    int i=0,top=0;
    struct TreeNode *p=NULL;
    stack[0]=root;
    while(top!=-1){
        while(stack[top]!=NULL){
            stack[++top]=stack[top]->left;//push
        }
        top--;//pop
        if(top!=-1){
            p=stack[top];
            res[i++]=p->val;
            stack[top]=p->right;
        }
    }
    *returnSize=i;
    return res;
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
    struct TreeNode **stack=(struct TreeNode**)malloc(sizeof(struct TreeNode*)*1000);
    int *res=(int*)malloc(sizeof(int)*10000);
    int top=-1;
    *returnSize=0;
    struct TreeNode *p=root;
    while(p!=NULL || top!=-1){
        if(p){
            stack[++top]=p;//push
            p=p->left;
        }else{
            p=stack[top--];//pop
            res[(*returnSize)++]=p->val;
            p=p->right;
        }
    }
    return res;
}

145.二叉树的后序遍历

1.递归

void postorder(struct TreeNode*root,int *returnSize,int *res){
    if(root==NULL){
        return;
    }
    postorder(root->left,returnSize,res);
    postorder(root->right,returnSize,res);
    res[(*returnSize)++]=root->val;
}
int size(struct TreeNode* root){
    if(root==NULL){
        return 0;
    }
    return size(root->left)+size(root->right)+1;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
    int treesize=size(root);
    int *res=(int *)malloc(sizeof(int)*treesize);
    *returnSize=0;
    postorder(root,returnSize,res);
    return res;
}

2.非递归

int* postorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize=0;
    struct TreeNode **stack=(struct TreeNode**)malloc(sizeof(struct TreeNode*)*1000);
    int *res=(int*)malloc(sizeof(int)*10000);
    int top=-1;
    struct TreeNode *p=root,*r;
    while(p || top!=-1){
        if(p){
            stack[++top]=p;//push
            p=p->left;
        }else{
            p=stack[top];
            if(p->right && p->right!=r){
                p=p->right;
                stack[++top]=p;
                p=p->left;
            }else{
                p=stack[top];
                res[(*returnSize)++]=p->val;
                top--;//pop
                r=p;
                p=NULL;
            }
        }
    }
    return res;
}

102.二叉树的层次遍历

题目描述

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

	3
   / \
  9  20
    /  \
   15   7

返回其层次遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

题目分析

int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes)

1、理解参数和返回值的含义,返回一个指针数组,每个成员指向当前下标所在层的所有节点(另一个数组)。returnSize为返回数组的个数。returnColumnSizes指向一个数组,每个成员对应返回数组里相同下标(某一层)指向的一维数组(存储所有节点)的个数。
2、用队列实现广度优先算法,注意每次循环,都需要把队列里属于某一层的节点全部出队。如果用指针队列需要注意统计当前队列的个数。

题解

#define MAX_SIZE 1000
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes){
 	 struct TreeNode*queue[MAX_SIZE]={0};
    int head=0,tail=0;
    if(root==NULL){
        *returnSize=0;
        return U=NULL;
    }
    int **res=(int**)malloc(sizeof(int *)*MAX_SIZE);//申请一个指针数组其元素为指针作为返回数组
    *returnColumnSizes=(int *)malloc(sizeof(int*)*MAX_SIZE);
    queue[tail++]=root;//push root
    *returnSize=0;
    while(head<tail){
        int size=(tail-head+MAX_SIZE)%MAX_SIZE;
        (*returnColumnSizes)[*returnSize]=size;
        res[*returnSize]=(int *)malloc(sizeof(int)*size);
        for(int i=0;i<size;i++){
            struct TreeNode*tmp=queue[head++];//pop queue
            res[*returnSize][i]=tmp->val;
            if(tmp->left){
                queue[tail++]=tmp->left;
            }
            if(tmp->right){
                queue[tail++]=tmp->right;
            }
        }
        (*returnSize)++;
    }
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值