LeetCode题解 二叉树(四):我要打十个?层序遍历变式九道

本文详细介绍了与二叉树的层次遍历相关的九道题目,包括层序遍历、右视图、层平均值、N叉树的层序遍历、寻找每层最大值以及填充节点的下一个右侧节点指针等问题。通过具体的代码实现,阐述了如何解决这些二叉树和N叉树的遍历问题,涵盖了从基础到进阶的各种解题思路。
摘要由CSDN通过智能技术生成

前言:

本篇涉及的题目都与10 二叉树的层序遍历有关,共九道题

  • 107.二叉树的层次遍历II medium
  • 199.二叉树的右视图 medium
  • 637.二叉树的层平均值 easy
  • 429.N叉树的前序遍历 medium
  • 515.在每个树行中找最大值 medium
  • 116.填充每个节点的下一个右侧节点指针 medium
  • 117.填充每个节点的下一个右侧节点指针II medium
  • 104.二叉树的最大深度 easy
  • 111.二叉树的最小深度 easy

正文

107 二叉树的层序遍历II medium

给定一个二叉树,返回其节点值自底向上的层次遍历。

和上一题相比,只是需要翻转一下最后结果而已,代码如下:

vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*> que;
        vector<vector<int>> res;
        if (root) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            for (int i = 0; i < size; i++) {
                TreeNode *temp = que.front();
                que.pop();
                vec.push_back(temp->val);
                if (temp->left) que.push(temp->left);
                if (temp->right) que.push(temp->right);
            }
            res.push_back(vec);
        }
        reverse(res.begin(), res.end());
        return res;
    }
199 二叉树的右视图 medium

做这道题首先要知道什么叫做二叉树的右视图,理解起来也简单,和初中学三视图的时候没什么两样,如下图所示,站在二叉树的右边,返回右侧能看到的所有值。

img

此处就要明确,如果当前层最右边有结点,如上图的结点4,将4加入结果就可以了。但如果没有呢?就需要将5加入节点,基于此要做一个判断。

那么怎么判断呢?其实也不难,当我们把每一层都加入队列后,最后一个元素,就是改层最右边的值,也是右视图能看见的值。

其余的和普通的层序遍历没有什么区别,代码如下:

vector<int> rightSideView(TreeNode* root) {
    queue<TreeNode*> que;
    vector<int> res;
    if (root) que.push(root);
    while (!que.empty()) {
        int size = que.size();
        for (int i = 0; i < size; i++) {
            TreeNode *temp = que.front();
            que.pop();
            if (i == (size - 1)) res.push_back(temp->val);
            if (temp->left) que.push(temp->left);
            if (temp->right) que.push(temp->right);
        }
    }
    return res;
}
637 二叉树的层平均值 easy

这,没什么可说的了,就是做一次普通的层序遍历,然后求一下每层的平均值而已。

代码如下:

vector<double> averageOfLevels(TreeNode* root) {
    queue<TreeNode*> que;
    vector<double> res;
    if (root) que.push(root);
    while (!que.empty()) {
        int size = que.size();
        double sum = 0;
        for (int i = 0; i <size; i++) {
            TreeNode *temp = que.front();
            que.pop();
            sum += temp->val;
            if (temp->left) que.push(temp->left);
            if (temp->right) que.push(temp->right);
        }
        res.push_back(sum / size);
    }
    return res;
}
429 N叉树的层序遍历 medium

不同之处在于,遍历子结点的时候,要用循环处理,其余和二叉树的层序遍历没什么区别,代码如下:

vector<vector<int>> levelOrder(Node* root) {
    queue<Node*> que;
    vector<vector<int>> res;
    if (root) que.push(root);
    while (!que.empty()) {
        int size = que.size();
        vector<int> vec;
        for (int i = 0; i < size; i++) {
            Node *cur = que.front();
            que.pop();
            vec.push_back(cur->val);
            // 此处为不同之处
            for (int j = 0; j < cur->children.size(); j++) {
                if (cur->children[j]) que.push(cur->children[j]);
            }
        }
        res.push_back(vec);
    }
    return res;
}
515 在每个树行中找最大值 medium

层序遍历,取每一层的最大值

vector<int> largestValues(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<int> result;
        while (!que.empty()) {
            int size = que.size();
            int maxValue = INT_MIN; // 取每一层的最大值
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                maxValue = node->val > maxValue ? node->val : maxValue;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(maxValue); // 把最大值放进数组
        }
        return result;
    }
116 填充每个节点的下一个右侧结点指针 medium

(这道题的题目给我一种日式轻小说的错觉

首先要明白题意,在这道题下,每个节点有一个next指针,需要让该指针指向右侧的结点,如下图所示:

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

本质还是层序遍历,但需要用每一层的第一个节点,并且记录上一个结点,令其指向当前结点,代码如下:

Node* connect(Node* root) {
        queue<Node*> que;
        if (root) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                Node* node = que.front();
                que.pop();
                // 如果不是本层的最后一个
                if (i != size -1) {
                    // 当前结点指向本层的下一个结点
                    node->next = que.front();
                } else 
                    node->next = NULL;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return root;
    }

其实这道题,如果用递归来做,会简洁很多,LeetCode官方版代码如下:

private:
    void traversal(Node* cur) {
        if (cur == NULL) return;
                                // 中
        if (cur->left) cur->left->next = cur->right; // 操作1
        if (cur->right) {
            if (cur->next) cur->right->next = cur->next->left; // 操作2
            else cur->right->next = NULL;
        }
        traversal(cur->left);   // 左
        traversal(cur->right);  // 右
    }
public:
    Node* connect(Node* root) {
        traversal(root);
        return root;
    }
117 填充每个节点下一个右侧节点指针II medium

和116的区别在于,这道题说的不是完全二叉树了,官方示例见下图:

img

但是思想还是一致的,我们直接用116的题解,就可以通过(LeetCode你有些偷懒啊)

代码如下,还是放一遍吧:

Node* connect(Node* root) {
        queue<Node*> que;
        if (root) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                Node* node = que.front();
                que.pop();
                // 如果不是本层的最后一个
                if (i != size -1) {
                    // 当前结点指向本层的下一个结点
                    node->next = que.front();
                } else 
                    node->next = NULL;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return root;
    }
104 二叉树的最大深度 easy

本质还是层序遍历,记录一共遍历了多少层就行,代码如下:

int maxDepth(TreeNode* root) {
    if (!root) return 0;
    int depth = 0;
    queue<TreeNode*> que;
    que.push(root);
    while (!que.empty()) {
        int size = que.size();
        for (int i = 0; i < size; i++) {
            TreeNode *node = que.front();
            que.pop();
            if (node->left) que.push(node->left);
            if (node->right) que.push(node->right);
        }
        depth++;
    }
    return depth;
}
111 二叉树的最小深度 easy

还是层序遍历,但是要注意一点,如果某个结点的左右子树都为空,就说明已经达到最小深度的那一层了,多了一个判断,代码如下:

int minDepth(TreeNode* root) {
    if (root == NULL) return 0;
    int depth = 0;
    queue<TreeNode*> que;
    que.push(root);
    while(!que.empty()) {
        int size = que.size();
        depth++; // 记录最小深度
        for (int i = 0; i < size; i++) {
            TreeNode* node = que.front();
            que.pop();
            if (node->left) que.push(node->left);
            if (node->right) que.push(node->right);
            if (!node->left && !node->right) { 
                return depth;
            }
        }
    }
    return depth;
}

这道题也可以用递归来做,代码如下:

int minDepth(TreeNode* root) {
    if (root == NULL) return 0;
    if (root->left == NULL && root->right != NULL) {
        return 1 + minDepth(root->right);
    }
    if (root->left != NULL && root->right == NULL) {
        return 1 + minDepth(root->left);
    }
    // 相当于左右子树都是空的
    return 1 + min(minDepth(root->left), minDepth(root->right));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值