代码随想录第十一天|二叉树的遍历

144.二叉树的前序遍历

题目链接:144. 二叉树的前序遍历 - 力扣(LeetCode)
题目描述:给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

img

输入:root = [1,null,2,3]
输出:[1,2,3]

示例 2:

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

示例 3:

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

示例 4:

img

输入:root = [1,2]
输出:[1,2]

示例 5:

img

输入:root = [1,null,2]
输出:[1,2]

提示:

  • 树中节点数目在范围 [0, 100]
  • -100 <= Node.val <= 100

解法一、递归

void preOrder(struct TreeNode* root, int* ret, int* returnSize) {
    if(root == NULL)
        return;
    ret[(*returnSize)++] = root->val;
    preOrder(root->left, ret, returnSize);
    preOrder(root->right, ret, returnSize);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    int* ret = (int*)malloc(sizeof(int) * 100);
    *returnSize = 0;
    preOrder(root, ret, returnSize);
    return ret;
}

解法二、迭代

前序遍历的顺序是根左右,就是先把根结点放入栈中,再将右孩子入栈,最后左孩子入栈,这样出栈的顺序就是前序遍历的顺序,因此可以写出迭代解法

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int* res = malloc(sizeof(int) * 2000);
    *returnSize = 0;
    if (root == NULL) {
        return res;
    }

    struct TreeNode* stk[2000];
    struct TreeNode* node = root;
    int stk_top = 0;
    while (stk_top > 0 || node != NULL) {
        while (node != NULL) {//先向左一直走,直到根结点左孩子为空
            res[(*returnSize)++] = node->val;//访问根
            stk[stk_top++] = node;//遍历左子树
            node = node->left;
        }
        node = stk[--stk_top];
        node = node->right;//遍历右子树
    }
    return res;
}

94.二叉树的中序遍历

题目链接:94. 二叉树的中序遍历 - 力扣(LeetCode)
题目描述:给定一个二叉树的根节点 root ,返回 它的 中序 遍历

示例 1:

img

输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

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

示例 3:

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

提示:

  • 树中节点数目在范围 [0, 100]
  • -100 <= Node.val <= 100

解法一、递归

void inOrder(struct TreeNode* node, int* ret, int* returnSize) {
    if(!node)
        return;
    inOrder(node->left, ret, returnSize);
    ret[(*returnSize)++] = node->val;
    inOrder(node->right, ret, returnSize);
}

int* inorderTraversal(struct TreeNode* root, int* returnSize){
    int* ret = (int*)malloc(sizeof(int) * 100);
    *returnSize = 0;
    inOrder(root, ret, returnSize);
    return ret;
}

解法二、迭代

栈用来保存结点而不是结点的值,这样写法就可以统一起来

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    *returnSize = 0;
    int* res = malloc(sizeof(int) * 501);
    struct TreeNode** stk = malloc(sizeof(struct TreeNode*) * 501);
    int top = 0;
    while (root != NULL || top > 0) {
        while (root != NULL) {//先向左一直走,直到根结点左孩子为空
            stk[top++] = root;
            root = root->left;//遍历左子树
        }
        root = stk[--top];// 此时root==null,说明上一步的root没有左子树
        res[(*returnSize)++] = root->val;//访问根
        //此时根结点为最左边的第一个左孩子或者最左边第一个没有左孩子但是可能有右孩子的结点
        //这样遍历顺序就为 左-根-右-左-根-右。。。或 根-左-根-右-左-根-右。。。
        root = root->right;//遍历右子树
    }
    return res;
}

145.二叉树的后序遍历

题目链接:145. 二叉树的后序遍历 - 力扣(LeetCode)
题目描述:给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

示例 1:

img

输入:root = [1,null,2,3]
输出:[3,2,1]

示例 2:

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

示例 3:

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

提示:

  • 树中节点的数目在范围 [0, 100]
  • -100 <= Node.val <= 100

解法一、递归

void postOrder(struct TreeNode* root, int* ret, int* returnSize) {
    if(node == NULL) 
        return;
    postOrder(root->left, ret, returnSize);
    postOrder(root->right, ret, returnSize);
    ret[(*returnSize)++] = root->val;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize){
    int* ret= (int*)malloc(sizeof(int) * 100);
    *returnSize = 0;
    postOrder(root, ret, returnSize);
    return ret;
}

解法二、迭代

后序遍历中,从栈中弹出的节点,我们只能确定其左子树肯定访问完了,但是无法确定右子树是否访问过。
因此,我们在后序遍历中,引入了一个prev来记录历史访问记录。
当访问完一棵子树的时候,我们用prev指向该节点。
这样,在回溯到父节点的时候,我们可以依据prev是指向左子节点,还是右子节点,来判断父节点的访问情况。

int *postorderTraversal(struct TreeNode *root, int *returnSize) {
    int *res = malloc(sizeof(int) * 2001);
    *returnSize = 0;
    if (root == NULL) {
        return res;
    }
    struct TreeNode **stk = malloc(sizeof(struct TreeNode *) * 2001);
    int top = 0;
    struct TreeNode *prev = NULL;
    while (root != NULL || top > 0) {
        while (root != NULL) {//遍历左子树
            stk[top++] = root;
            root = root->left;
        }
        //从栈中弹出的元素,左子树一定是访问完了的
        root = stk[--top];
        //如果没有右子树,或者右子树访问完了,也就是上一个访问的节点是右子节点时
        //说明可以访问当前节点
        if (root->right == NULL || root->right == prev) {
            res[(*returnSize)++] = root->val;
            //更新历史访问记录,这样回溯的时候父节点可以由此判断右子树是否访问完成
            prev = root;
            root = NULL;
        } else {
            //如果右子树没有被访问,那么将当前节点压栈,访问右子树
            stk[top++] = root;
            root = root->right;
        }
    }
    return res;
}

层序遍历

102.二叉树的层序遍历

题目链接:102. 二叉树的层序遍历 - 力扣(LeetCode)

题目描述:给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:

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

示例 3:

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

提示:

  • 树中节点数目在范围 [0, 2000]
  • -1000 <= Node.val <= 1000

使用辅助队列

设置辅助队列(数组),每次从头部弹出一层的结点,并把这些结点的左右子结点加入队列尾部,直到队列为空

int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes){
    int** ans=(int**)malloc(sizeof(int*)*2000);
    *returnSize=0;
    if(!root) return NULL;//要在return前给出*returnSize的取值不然过不去;!!
    int columnSizes[2000];//记录每一行的列数(每层结点数),因为要给出* returnColumnSizes
    struct TreeNode* queue[2000];//模拟队列
    int rear=0,front=0;//记录队列头尾
    queue[rear++]=root;//录入根结点

    while(front!=rear){//队列不为空
        ans[(*returnSize)]=(int*)malloc(sizeof(int)*(rear-front));
        columnSizes[(*returnSize)]=rear-front;
        int start=front;//记录遍历开始位置,即为本层的头
        front=rear;//本层的尾部成为下次的头,因为所有的元素均弹出队列
        //在这里下层的头节点front同时作为遍历结束的位置,因为在遍历中rear会不断改变,成为下层的尾
        for(int i=start;i<front;i++){//弹出start到未变化的rear(即为front)之间的所有元素
            ans[(*returnSize)][i-start]=queue[i]->val;
            if(queue[i]->left) queue[rear++]=queue[i]->left;
            if(queue[i]->right) queue[rear++]=queue[i]->right;//rear不断改变
        }
        (*returnSize)++;//一层遍历完*returnSize加一;
       
    }
    //给出*returnColumnSizes
    *returnColumnSizes=(int*)malloc(sizeof(int)*(*returnSize));
    for(int i=0;i<*returnSize;i++) (*returnColumnSizes)[i]=columnSizes[i];
    return ans;
}

107.二叉树的层序遍二叉树的层序遍历 II

题目链接:107. 二叉树的层序遍历 II - 力扣(LeetCode)

题目描述:给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]

示例 2:

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

示例 3:

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

提示:

  • 树中节点数目在范围 [0, 2000]
  • -1000 <= Node.val <= 1000

正常层序遍历+反转数组

int** levelOrderBottom(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    int** levelOrder = malloc(sizeof(int*) * 2001);
    *returnColumnSizes = malloc(sizeof(int) * 2001);
    *returnSize = 0;
    if (!root) {
        return levelOrder;
    }
    struct TreeNode** q = malloc(sizeof(struct TreeNode*) * 2001);
    int left = 0, right = 0;
    q[right++] = root;
    while (left < right) {
        int len = right - left;
        int* level = malloc(sizeof(int) * len);
        (*returnColumnSizes)[*returnSize] = len;
        for (int i = 0; i < len; ++i) {
            struct TreeNode* node = q[left++];
            level[i] = node->val;
            if (node->left != NULL) {
                q[right++] = node->left;
            }
            if (node->right != NULL) {
                q[right++] = node->right;
            }
        }
        levelOrder[(*returnSize)++] = level;
    }
    for (int i = 0; 2 * i < *returnSize; ++i) {
        int* tmp1 = levelOrder[i];
        levelOrder[i] = levelOrder[(*returnSize) - i - 1];
        levelOrder[(*returnSize) - i - 1] = tmp1;
        int tmp2 = (*returnColumnSizes)[i];
        (*returnColumnSizes)[i] = (*returnColumnSizes)[(*returnSize) - i - 1];
        (*returnColumnSizes)[(*returnSize) - i - 1] = tmp2;
    }
    return levelOrder;
}

199.二叉树的右视图

题目链接:199. 二叉树的右视图 - 力扣(LeetCode)

题目描述:给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例 1:

img

输入: [1,2,3,null,5,null,4]
输出: [1,3,4]

示例 2:

输入: [1,null,3]
输出: [1,3]

示例 3:

输入: []
输出: []

提示:

  • 二叉树的节点个数的范围是 [0,100]
  • -100 <= Node.val <= 100

思路

层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。

int* rightSideView(struct TreeNode* root, int* returnSize) {
    int* ans = (int*)malloc(sizeof(int) * 200);
    *returnSize = 0;
    if (!root)
        return NULL; // 要在return前给出*returnSize的取值不然过不去;!!
    struct TreeNode* queue[2000]; // 模拟队列
    int rear = 0, front = 0;      // 记录队列头尾
    queue[rear++] = root;         // 录入根结点
    while (front != rear) { // 队列不为空
        int start = front; // 记录遍历开始位置,即为本层的头
        front = rear; // 本层的尾部成为下次的头,因为所有的元素均弹出队列
        // 在这里下层的头节点front同时作为遍历结束的位置,因为在遍历中rear会不断改变,成为下层的尾
        for (int i = start; i < front; i++) { 
            if (i == front - 1) { // 遍历到本层最右边的结点,将该结点记录进答案数组
                ans[(*returnSize)] = queue[i]->val;
            }
            if (queue[i]->left)
                queue[rear++] = queue[i]->left;
            if (queue[i]->right)
                queue[rear++] = queue[i]->right; // rear不断改变
        }
        (*returnSize)++; // 一层遍历完*returnSize加一;
    }
    return ans;
}

637.二叉树的层平均值

题目链接:637. 二叉树的层平均值 - 力扣(LeetCode)

题目描述:给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:[3.00000,14.50000,11.00000]
解释:第 0 层的平均值为 3,第 1 层的平均值为 14.5,第 2 层的平均值为 11 。
因此返回 [3, 14.5, 11] 。

示例 2:

img

输入:root = [3,9,20,15,7]
输出:[3.00000,14.50000,11.00000]

提示:

  • 树中节点数量在 [1, 104] 范围内
  • -231 <= Node.val <= 231 - 1

思路

层序遍历时,每层求和再取平均值即可

double *averageOfLevels(struct TreeNode *root, int *returnSize) {
    double *ans = (int*)malloc(sizeof(double)*10000);
    *returnSize = 0;
    struct TreeNode *queue[10000];
    int rear = 0,front = 0;
    queue[rear++] = root;
    while(front != rear){
        double sum = 0;
        int len = rear - front;
        for(int i=0;i<len;i++){
            struct TreeNode *node = queue[front++];
            sum += node->val;//计算该层所有结点的值的和
            if(node->left) queue[rear++] = node->left;
            if(node->right) queue[rear++] = node->right;
        }
        ans[(*returnSize)++] = sum/len;//计算每层的平均值
    }
    return ans;
}

429.N叉树的层序遍历

题目链接:429. N 叉树的层序遍历 - 力扣(LeetCode)

题目描述:给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。

树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

示例 1:

img

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

示例 2:

img

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]

提示:

  • 树的高度不会超过 1000
  • 树的节点总数在 [0, 104] 之间

思路

相比于层序遍历二叉树,N叉树只是多了一个遍历孩子结点的过程

#define MAX_LEVE_SIZE 1000
#define MAX_NODE_SIZE 10000

int **levelOrder(struct Node *root, int *returnSize, int **returnColumnSizes) {
    int **ans = (int **) malloc(sizeof(int *) * MAX_LEVE_SIZE);
    *returnColumnSizes = (int *) malloc(sizeof(int) * MAX_LEVE_SIZE);
    *returnSize = 0;
    if (root == NULL)
        return ans;
    struct Node **queue = (struct Node **) malloc(sizeof(struct Node *) * MAX_NODE_SIZE);
    int rear = 0, front = 0;
    queue[rear++] = root;
    while (front != rear) {
        int size = rear - front;
        (*returnColumnSizes)[*returnSize] = size;
        int *level = (int *) malloc(sizeof(int) * size);
        for (int i = 0; i < size; i++) {
            struct Node *node = queue[front++];
            level[i] = node->val;
            for (int j = 0; j < node->numChildren; j++) {//遍历所有孩子结点
                queue[rear++] = node->children[j];
            }
        }
        ans[(*returnSize)++] = level;
    }
    return ans;
}

515.在每个树行中找最大值

题目链接:515. 在每个树行中找最大值 - 力扣(LeetCode)

题目描述:给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

示例1:

img

输入: root = [1,3,2,5,3,null,9]
输出: [1,3,9]

示例2:

输入: root = [1,2,3]
输出: [1,3]

提示:

  • 二叉树的节点个数的范围是 [0,104]
  • -231 <= Node.val <= 231 - 1

思路

正常层序遍历,遍历每层的时候记录该层的最大值即可

#define MAX_SIZE 10000

int *largestValues(struct TreeNode *root, int *returnSize) {
    int *ans = (int *) malloc(sizeof(int) * MAX_SIZE);
    *returnSize = 0;
    if (!root) {
        return ans;
    }
    struct TreeNode *queue[MAX_SIZE];
    int rear = 0, front = 0;
    queue[rear++] = root;
    while (front != rear) {
        int max = INT_MIN;
        int size = rear - front;
        for (int i = 0; i < size; i++) {
            struct TreeNode *node = queue[front++];
            max = node->val > max ? node->val : max;
            if (node->left) queue[rear++] = node->left;
            if (node->right) queue[rear++] = node->right;
        }
        ans[(*returnSize)++] = max;
    }
    return ans;
}

填充每个节点的下一个右侧节点指针

题目链接:116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)

题目描述:给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL

初始状态下,所有 next 指针都被设置为 NULL

示例 1:

img

输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。

示例 2:

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

提示:

  • 树中节点的数量在 [0, 212 - 1] 范围内
  • -1000 <= node.val <= 1000

思路

本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了

#define MAX_SIZE 5000
//版本一、使用辅助结点pre记录前一个结点
struct Node *connect(struct Node *root) {
    if (!root) {
        return root;
    }
    struct Node *queue[MAX_SIZE];
    int rear = 0, front = 0;
    queue[rear++] = root;
    while (front != rear) {
        int size = rear - front;
        struct Node *pre;
        struct Node *cur;
        for (int i = 0; i < size; i++) {// 遍历这一层的所有节点
            if (i == 0) {
                pre = queue[front++];
                cur = pre;
            } else {
                cur = queue[front++];
                pre->next = cur;
                pre = cur;
            }
            // 拓展下一层节点
            if (cur->left) queue[rear++] = cur->left;
            if (cur->right) queue[rear++] = cur->right;
        }
    }
    return root;
}
//版本二、不使用辅助结点,直接链接
struct Node* connect(struct Node* root) {
    if (!root) {
        return root;
    }
    struct Node* queue[MAX_SIZE];
    int rear = 0, front = 0;
    queue[rear++] = root;
    while (front != rear) {
        int size = rear - front;
        for (int i = 0; i < size; i++) {// 遍历这一层的所有节点
            struct Node* node = queue[front++];// 从队首取出元素
            // 连接,由于队列是先进先出,此时的队头节点一定是当前结点的右兄弟
            if (i < size - 1) {
                node->next = queue[front];
            }
            // 拓展下一层节点
            if (node->left)
                queue[rear++] = node->left;
            if (node->right)
                queue[rear++] = node->right;
        }
    }
    return root;
}

117.填充每个节点的下一个右侧节点指针II

题目链接:117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)

题目描述:给定一个二叉树:

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL

初始状态下,所有 next 指针都被设置为 NULL

示例 1:

img

输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),'#' 表示每层的末尾。

示例 2:

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

提示:

  • 树中的节点数在范围 [0, 6000]
  • -100 <= Node.val <= 100

思路

上一题是完全二叉树,本题虽然是二叉树,但思路解法与上一题完全一样。

//版本一、使用辅助结点pre记录前一个结点
#define MAX_SIZE 5000
struct Node *connect(struct Node *root) {
    if (!root) {
        return root;
    }
    struct Node *queue[MAX_SIZE];
    int rear = 0, front = 0;
    queue[rear++] = root;
    while (front != rear) {
        int size = rear - front;
        struct Node *pre;
        struct Node *cur;
        for (int i = 0; i < size; i++) {// 遍历这一层的所有节点
            if (i == 0) {
                pre = queue[front++];
                cur = pre;
            } else {
                cur = queue[front++];
                pre->next = cur;
                pre = cur;
            }
            // 拓展下一层节点
            if (cur->left) queue[rear++] = cur->left;
            if (cur->right) queue[rear++] = cur->right;
        }
    }
    return root;
}
//版本二、不使用辅助结点,直接链接
#define MAX_SIZE 5000
struct Node* connect(struct Node* root) {
    if (!root) {
        return root;
    }
    struct Node* queue[MAX_SIZE];
    int rear = 0, front = 0;
    queue[rear++] = root;
    while (front != rear) {
        int size = rear - front;
        for (int i = 0; i < size; i++) {// 遍历这一层的所有节点
            struct Node* node = queue[front++];// 从队首取出元素
            // 连接,由于队列是先进先出,此时的队头节点一定是当前结点的右兄弟
            if (i < size - 1) {
                node->next = queue[front];
            }
            // 拓展下一层节点
            if (node->left)
                queue[rear++] = node->left;
            if (node->right)
                queue[rear++] = node->right;
        }
    }
    return root;
}

104.二叉树的最大深度

题目链接:104. 二叉树的最大深度 - 力扣(LeetCode)

题目描述:给定一个二叉树 root ,返回其最大深度。

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

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:3

示例 2:

输入:root = [1,null,2]
输出:2

提示:

  • 树中节点的数量在 [0, 104] 区间内。
  • -100 <= Node.val <= 100

解法一、深度优先搜索–递归

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

解法二、广度优先搜索–迭代

通过层次遍历,当遍历到最后一层,层数即二叉树的深度

#define MAX_SIZE 10000
int maxDepth(struct TreeNode* root) {
    int ans = 0;
    if (!root) {
        return ans;
    }
    struct TreeNode* queue[MAX_SIZE];
    int rear = 0, front = 0;
    queue[rear++] = root;
    while (front != rear) {
        int size = rear - front;
        for (int i = 0; i < size; i++) { // 遍历这一层的所有节点
            struct TreeNode* node = queue[front++]; 
            if (node->left)
                queue[rear++] = node->left;
            if (node->right)
                queue[rear++] = node->right;
        }
        ans++;//层数+1
    }
    return ans;
}

111.二叉树的最小深度

题目链接:111. 二叉树的最小深度 - 力扣(LeetCode)

题目描述:给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

**说明:**叶子节点是指没有子节点的节点。

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:2

示例 2:

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

提示:

  • 树中节点数的范围在 [0, 105]
  • -1000 <= Node.val <= 1000

解法一、深度优先搜索–递归

对于每一个非叶子节点,我们只需要分别计算其左右子树的最小叶子节点深度。这样就将一个大问题转化为了小问题,可以递归地解决该问题,需要注意的是只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点

int minDepth(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }

    if (root->left == NULL && root->right == NULL) {
        return 1;
    }

    int min_depth = INT_MAX;
    if (root->left != NULL) {
        min_depth = fmin(minDepth(root->left), min_depth);
    }
    if (root->right != NULL) {
        min_depth = fmin(minDepth(root->right), min_depth);
    }

    return min_depth + 1;
}

解法二、广度优先搜索–迭代

#define MAX_SIZE 100000
int minDepth(struct TreeNode* root) {
    int ans = 0;
    if (!root) {
        return ans;
    }
    struct TreeNode* queue[MAX_SIZE];
    int rear = 0, front = 0;
    queue[rear++] = root;
    while (front != rear) {
        int size = rear - front;
        ans++;                           // 层数+1
        for (int i = 0; i < size; i++) { // 遍历这一层的所有节点
            struct TreeNode* node = queue[front++];
            if (node->left)
                queue[rear++] = node->left;
            if (node->right)
                queue[rear++] = node->right;
            // 当左右孩子都为空的时候,说明是最低点的一层了,退出
            if (!node->left && !node->right) {
                return ans;
            }
        }
    }
    return ans;
}

最近更新

  1. Spring 系列

    2024-07-11 01:28:02       0 阅读
  2. 什么是CRISPR/Cas9?

    2024-07-11 01:28:02       0 阅读

热门阅读

  1. 二刷算法训练营Day57 | 动态规划(17/17)

    2024-07-11 01:28:02       6 阅读
  2. 自定义业务非受检异常

    2024-07-11 01:28:02       7 阅读
  3. GPT-5 一年半后发布?对此你有何期待?

    2024-07-11 01:28:02       6 阅读
  4. DSC主备归档报错

    2024-07-11 01:28:02       8 阅读
  5. DangerWind-RPC-framework---三、服务端下机

    2024-07-11 01:28:02       5 阅读
  6. spring管理bean源码解析

    2024-07-11 01:28:02       6 阅读
  7. a+=1和a=a+1的区别

    2024-07-11 01:28:02       5 阅读
  8. threadLocal

    2024-07-11 01:28:02       6 阅读
  9. GESP C++ 三级真题(2023年9月)T2 进制判断

    2024-07-11 01:28:02       5 阅读
  10. qt中connect函数的使用方法

    2024-07-11 01:28:02       9 阅读