接上篇,先来看106题,此题与105题类似,是通过中序和后序遍历结果复原二叉树。
还是选择递归的方法:
首先看题目函数的参数:
struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize)
中序的首结点和结点数,后序的首结点和结点数。
那么第一步就是判空,通过结点数进行判断。
其次,根结点的位置是后序遍历的最后一个,先对根结点进行赋值,然后找到根结点在中序遍历中的位置。
对于根结点在中序遍历中的位置坐标i(第i+1个,root=inorder[i]),其左边为左子树,共i个元素,右边为右子树,共size-i-1,对于后序遍历,前i个元素为左子树,第i+1个元素到倒数第二个元素为右子树,进行递归。
C语言代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){
if (inorderSize <= 0 || postorderSize <= 0) return NULL;
struct TreeNode* p = (struct TreeNode*)malloc(sizeof(struct TreeNode));
int i;
p->val = postorder[postorderSize-1];//后序的最后一个是根结点
p->left = NULL;
p->right = NULL;
//查找根结点在中序中的位置
for(i = 0; i < inorderSize; i++)
{
if (inorder[i] == p->val)
break;
}
p->left = buildTree(inorder, i, postorder, i);
p->right = buildTree(inorder + i + 1, inorderSize - i - 1, postorder + i, postorderSize - i - 1);
return p;
}
第104题,简单难度,求二叉树最大深度。
显然,是返回左子树和右子树的深度中较大的一个。可以写成return left_depth>right_depth?left_depth:right_depth;
第一步仍然是判空,空树返回0即可。
第二步分别初始化左右子树高度为1。
第三步递归调用函数求解左右子树高度。
C语言代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int maxDepth(struct TreeNode* root){
struct TreeNode *p = (struct TreeNode *)malloc(sizeof(struct TreeNode));
p = root;
int left_depth = 1;
int right_depth = 1;
if(p==NULL) return 0;
left_depth += maxDepth(p->left);
right_depth += maxDepth(p->right);
return left_depth>right_depth?left_depth:right_depth;
}
同时,这种思路其实也是深度优先的思想。
另一种方法是广度优先的思想,通过队列辅助实现:
1,构建队列,实现入队和出队函数
2,利用队列先进先出的特性实现二叉树的层序遍历
3,将二叉树根 root 压入队列,并将 NULL 作为每层的区分节点也压入队列
4,遇到层的区分节点则处理下一层,直到队列为空
//队列结点结构
typedef struct QueueNode {
struct TreeNode *data; //二叉树结点指针
struct QueueNode *next; //队列元素下一个结点指针
} QueueNode_t;
//队列结构
typedef struct LinkQueue {
int count; //队列元素个数
QueueNode_t *front; //队列头结点
QueueNode_t *rear; //队列尾结点
} LinkQueue_t;
//队列初始化
int initQueue(LinkQueue_t *queue) {
queue->front = queue->rear = malloc(sizeof(QueueNode_t));
if (NULL == queue->front)
return -1;
queue->front->next = NULL;
queue->count = 0;
return 0;
}
//入队函数
int enqueue(LinkQueue_t *queue, struct TreeNode *data) {
QueueNode_t *newNode = malloc(sizeof(QueueNode_t));
if (NULL == newNode)
return -1;
newNode->data = data;
newNode->next = NULL;
queue->rear->next = newNode;
queue->rear = newNode;
queue->count++;
return 0;
}
//出队函数
int dequeue(LinkQueue_t *queue, struct TreeNode *data) {
if (queue->front == queue->rear) {
return -1;
}
QueueNode_t *denode = queue->front->next;//指向待出队元素
*data = denode->data;
queue->front->next = denode->next;//尾指针与后一个元素相连
if (denode == queue->rear) {
queue->rear = queue->front;
}
free(denode);
queue->count--;
return 0;
}
//队列销毁
void destroyQueue(LinkQueue_t *queue) {
/*q->front 指向头node, queue->rear指向下一个节点,这里当临时指针用*/
while (queue->front) {
queue->rear = queue->front->next;
free(queue->front);
queue->front = queue->rear;
}
}
//队列判空
int emptyQueue(LinkQueue_t *queue) {
return queue->front == queue->rear ? 1 : 0;
}
int maxDepth(struct TreeNode *root) {
if (NULL == root)
return 0;
int max = 0, i = 0, cnt = 0;
struct TreeNode *data = NULL;
LinkQueue_t queue;
initQueue(&queue);
enqueue(&queue, root);//根结点进入队列
while (!emptyQueue(&queue)) {
cnt = queue.count;
for (i = 0; i < cnt; i++) {
dequeue(&queue, &data);
if (data->left) {//存在左子树,左节点进队
enqueue(&queue, data->left);
}
if (data->right) {//存在右子树,右节点进队
enqueue(&queue, data->right);
}
}
max++;
}
destroyQueue(&queue);
return max;
}
和此题相对应的是第111题,求二叉树的最小深度,也要略复杂一点儿。
首先,这次不能单纯的比较左右子树小的一方,需要分情况讨论:
第一种情况,空树直接返回0;
第二种情况,只有根结点,返回1;
第三种情况,有左节点无右节点,递归左子树;
第四种情况,有右节点无左节点,递归右子树;
第五种情况,两侧均有,分别递归左右子树,返回最小值+1;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int minDepth(struct TreeNode* root){
struct TreeNode *p = (struct TreeNode*)malloc(sizeof(struct TreeNode));
p = root;
int left_depth = 0;
int right_depth = 0;
if (p==NULL) return 0;
else if (p->left==NULL && p->right==NULL) return 1;
else if (p->left!=NULL && p->right==NULL) return 1 + minDepth(p->left);
else if (p->left==NULL && p->right!=NULL) return 1 + minDepth(p->right);
else{
left_depth = 1 + minDepth(p->left);
right_depth = 1 + minDepth(p->right);
return left_depth<right_depth?left_depth:right_depth;
}
}
BFS:
如果出现叶子节点,就返回当前深度。
//方法二:BFS
typedef struct QueueNode {
struct TreeNode *data;
struct QueueNode *next;
} QueueNode_t;
typedef struct LinkQueue {
int count;
QueueNode_t *front;
QueueNode_t *rear;
} LinkQueue_t;
int initQueue(LinkQueue_t *queue) {
queue->front = queue->rear = malloc(sizeof(QueueNode_t));
if (NULL == queue->front)
return -1;
queue->front->next = NULL;
queue->count = 0;
return 0;
}
int enqueue(LinkQueue_t *queue, struct TreeNode *data) {
QueueNode_t *newNode = malloc(sizeof(QueueNode_t));
if (NULL == newNode) {
return -1;
}
newNode->data = data;
newNode->next = NULL;
queue->rear->next = newNode;
queue->rear = newNode;
queue->count++;
return 0;
}
int dequeue(LinkQueue_t *queue, struct TreeNode **data) {
if (queue->front == queue->rear) {
return -1;
}
QueueNode_t *denode = queue->front->next;
*data = denode->data;
queue->front->next = denode->next;
if (denode == queue->rear) {
queue->rear = queue->front;
}
free(denode);
queue->count--;
return 0;
}
void destroyQueue(LinkQueue_t *queue) {
/*q->front 指向头node, queue->rear指向下一个节点,这里当临时指针用*/
while (queue->front) {
queue->rear = queue->front->next;
free(queue->front);
queue->front = queue->rear;
}
}
int emptyQueue(LinkQueue_t *queue) {
return queue->front == queue->rear ? 1 : 0;
}
int minDepth(struct TreeNode *root) {
if (NULL == root)
return 0;
int max = 0, i = 0, cnt = 0;
struct TreeNode *data = NULL;
LinkQueue_t queue;
initQueue(&queue);
enqueue(&queue, root);
while (!emptyQueue(&queue)) {
cnt = queue.count;
max++;
for (i = 0; i < cnt; i++) {
dequeue(&queue, &data);
if (NULL == data->left && NULL == data->right) {
return max;
}
if (data->left) {
enqueue(&queue, data->left);
}
if (data->right) {
enqueue(&queue, data->right);
}
}
}
destroyQueue(&queue);
return max;
}