leetcode刷题笔记(二)

接上篇,先来看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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值