此篇博客用于记录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)++;
}
}