【LeetCode】二叉树的广度优先遍历

前言

本文展示LeetCode中与二叉树广度优先遍历(层序遍历)的变体相关的题目,读者可以用来借此默写以检验是否熟悉相关算法,其难度为简单或中等,我们会给出最基础的层序遍历算法,然后推荐读者熟练掌握相关变体算法。

LeetCode题目

相关题目类型

相关链接

102

二叉树的层序遍历-按层输出(中等难度)

https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

107

二叉树的层序遍历II-按层反转输出(中等难度)

https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/

199

二叉树的右视图-按层输出最后一个(中等难度)

https://leetcode-cn.com/problems/binary-tree-right-side-view/

637

二叉树的层平均值-按层取均值(简单难度)

https://leetcode-cn.com/problems/average-of-levels-in-binary-tree/

429

N叉树的层序遍历-按层输出(中等难度)

https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/

515

在每个树行中找最大值-按层取最大值(中等难度)

https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/

116

填充每个节点的下一个右侧结点指针(中等难度)

https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/

117

填充每个节点的下一个右侧结点指针II(中等难度)

https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/

虽然上述有8道题目,但是最根本的是第一道题目,请读者在理解第一道题目的基础上做其他7道就会非常容易。

一、最简单的层序遍历

假设我们有如下二叉树:

image.png

如果希望经过层序遍历得到连续输出[3,9,20,15,7]

我们之前已经讲解过该算法的迭代实现,可以借助队列仿照先序遍历流程:

即“层序遍历同先序,借用队列先左右”,

相关Python3代码如下:

def levelOrder(self, root: TreeNode) -> List[List[int]]:
        result = []
        if not root:
            return result
        queue = [root]
        while len(queue)>0:
            cur = queue.pop(0)
            result.append(cur.val)
            if cur.left:
                queue.append(cur.left)
            if cur.right:
                queue.append(cur.right)
        return result
对应的C++代码:
vector<int> levelOrder(TreeNode* node) {
        vector<int> result;
        if (node == NULL) {
            return result;
        }
        queue<TreeNode*> queue;
        queue.push(node);
        while (!queue.empty()) {
            TreeNode* cur = queue.front();
            result.push_back(cur->val);
            queue.pop();
            if (cur->left) {
                queue.push(cur->left);
            }
            if (cur->right) {
                queue.push(cur->right);
            }
        }
        return result;
    }

二、层序遍历的变体

1、102.⼆叉树的层序遍历(按层输出)

题⽬链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

如果希望经过层序遍历得到按层输出:[[3],[9,20],[15,7]]

我们在上述代码中进行更改,相关Python3代码如下:

def levelOrder(self, root: TreeNode) -> List[List[int]]:
        result = []
        if not root:
            return result
        queue = [root]
        while len(queue)>0:
            length = len(queue)
            level_result = []
            for i in range(0,length):
                cur = queue.pop(0)
                level_result.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(level_result)
        return result

我们可以执行代码来理解流程:

第一次循环时,length=1,cur = root ,queue中只有root=3,将其出队,root.val加入level_result

cur.left和cur.right都存在,加入队列,此时队列中有第二层的两个节点;

第二次循环时,length=2,cur = 9节点时 ,将其出队加入level_result,然后左右节点不存在不需要添加;

cur = 20节点时 ,将其出队加入level_result,然后左右节点存在需要添加到队列,此时队列中有第三层的两个节点;

即每次循环,第一层循环负责循环二叉树的每一层,第二层循环负责循环二叉树的每一层的节点,并将下一层节点加入队列。

这里给出C++代码:

vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        if(root==NULL){
            return result;
        }
        queue<TreeNode*> queue;
        queue.push(root);
        while(!queue.empty()){
            int size = queue.size();
            vector<int> level_result;
            for(int i=0;i<size;i++){
                TreeNode* cur=queue.front();
                queue.pop();
                level_result.push_back(cur->val);
                if (cur->left!=NULL){
                    queue.push(cur->left);
                }
                if (cur->right!=NULL){
                    queue.push(cur->right);
                }
            }
            result.push_back(level_result);
        }
        return result;
    }

2、107.⼆叉树的层序遍历(按层反转输出)

题⽬链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/

该题希望经过层序遍历得到按层反转输出:[[15,7],[9,20],[3]]

最简单的做法就是在之前代码返回result前添加反转操作。

C++需要在“return result;”前添加如下语句:

reverse(result.begin(),result.end());

Python需要在“return result;”前添加如下语句:

result = result[::-1]

3、199.⼆叉树的右视图(按层输出最后一个)

题⽬链接:https://leetcode-cn.com/problems/binary-tree-right-side-view/

该题描述如下:

image.png

该题非常简单,在每层加入result时,只加入每层最后一个即可。

C++版本:

vector<int> rightSideView(TreeNode* root) {
        vector<int> result;
        if(root==NULL){
            return result;
        }
        queue<TreeNode*> queue;
        queue.push(root);
        while(!queue.empty()){
            int size = queue.size();
            for(int i=0;i<size;i++){
                TreeNode* cur=queue.front();
                queue.pop();
                if(i==size-1){
                    result.push_back(cur->val);
                }
                if (cur->left!=NULL){
                    queue.push(cur->left);
                }
                if (cur->right!=NULL){
                    queue.push(cur->right);
                }
            }
        }
        return result;
    }

Python版本:

def rightSideView(self, root: TreeNode) -> List[int]:
        result = []
        if not root:
            return result
        queue = [root]
        while len(queue)>0:
            length = len(queue)
            for i in range(0,length):
                cur = queue.pop(0)
                if i==length-1:
                    result.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
        return result

4、637.⼆叉树的层平均值(按层取平均值)

题⽬链接:https://leetcode-cn.com/problems/average-of-levels-in-binary-tree/

该题描述如下:

image.png

该题只要把每层的数累加起来求均值即可,注意C++要将sum定义为double,不然精度不足

C++版本:

vector<double> averageOfLevels(TreeNode* root) {
        vector<double> result;
        if(root==NULL){
            return result;
        }
        queue<TreeNode*> queue;
        queue.push(root);
        while(!queue.empty()){
            int size = queue.size();
            double sum = 0;
            for(int i=0;i<size;i++){
                TreeNode* cur=queue.front();
                queue.pop();
                sum+=cur->val;
                if (cur->left!=NULL){
                    queue.push(cur->left);
                }
                if (cur->right!=NULL){
                    queue.push(cur->right);
                }
            }
            result.push_back(sum/size);
        }
        return result;
    }

Python版本:

def averageOfLevels(self, root: TreeNode) -> List[float]:
        result = []
        if not root:
            return result
        queue = [root]
        while len(queue)>0:
            length = len(queue)
            sum=0.0
            for i in range(0,length):
                cur = queue.pop(0)
                sum+=cur.val
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(sum/length)
        return result

5、429.N叉树的层序遍历(按层输出)

题⽬链接:https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/

该题描述如下:

image.png

该题只要把遍历一下children数组即可

C++版本:

vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> result;
        if(root==NULL){
            return result;
        }
        queue<Node*> queue;
        queue.push(root);
        while(!queue.empty()){
            int size = queue.size();
            vector<int> level_result;
            for(int i=0;i<size;i++){
                Node* cur=queue.front();
                queue.pop();
                level_result.push_back(cur->val);
                for(int j=0;j<cur->children.size();j++){
                    if (cur->children[j]!=NULL){
                        queue.push(cur->children[j]);
                    }
                }
            }
            result.push_back(level_result);
        }
        return result;
    }

Python版本:

def levelOrder(self, root: 'Node') -> List[List[int]]:
        result = []
        if not root:
            return result
        queue = [root]
        while len(queue)>0:
            length = len(queue)
            level_result = []
            for i in range(0,length):
                cur = queue.pop(0)
                level_result.append(cur.val)
                for child in cur.children:
                    if child:
                        queue.append(child)
            result.append(level_result)
        return result

6、515.在每个树⾏中找最⼤值(按层输出)

题⽬链接:https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/

该题描述如下:

image.png

该题需要注意的是,取最大值,最大值的初始值要设置为整数的最小值。

在C++中为INT_MIN,在Python中为-sys.maxsize - 1。

C++版本:

vector<int> largestValues(TreeNode* root) {
        vector<int> result;
        if(root==NULL){
            return result;
        }
        queue<TreeNode*> queue;
        queue.push(root);
        while(!queue.empty()){
            int size = queue.size();
            int max = INT_MIN;
            for(int i=0;i<size;i++){
                TreeNode* cur=queue.front();
                queue.pop();
                if (max<cur->val){
                    max = cur->val;
                }
                if (cur->left!=NULL){
                    queue.push(cur->left);
                }
                if (cur->right!=NULL){
                    queue.push(cur->right);
                }
            }
            result.push_back(max);
        }
        return result;
    }

Python版本:

def largestValues(self, root: TreeNode) -> List[int]:
        result = []
        if not root:
            return result
        queue = [root]
        while len(queue)>0:
            length = len(queue)
            max=-sys.maxsize - 1
            for i in range(0,length):
                cur = queue.pop(0)
                if max<cur.val:
                    max=cur.val
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(max)
        return result

7、116.填充每个节点的下⼀个右侧节点指针(按层输出)

题⽬链接:https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/

该题描述如下:

image.png

该题需要注意的是理解题目,输入root,返回root,二叉树的存储结构要改变。

C++版本:

Node* connect(Node* root) {
        if(root==NULL){
            return root;
        }
        queue<Node*> queue;
        queue.push(root);
        while(!queue.empty()){
            int size = queue.size();
            vector<Node*> level_node;//记录每层的node
            for(int i=0;i<size;i++){
                Node* cur=queue.front();
                queue.pop();
                level_node.push_back(cur);
                if (cur->left!=NULL){
                    queue.push(cur->left);
                }
                if (cur->right!=NULL){
                    queue.push(cur->right);
                }
            }
            //连接next
            for(int i=0;i<size;i++){
                if (i==size-1){
                    level_node[i]->next = NULL;
                }
                else{
                    level_node[i]->next = level_node[i+1];
                }
            }
        }
        return root;
    }

Python版本:

def connect(self, root: 'Node') -> 'Node':
        if not root:
            return root
        queue = [root]
        while len(queue)>0:
            length = len(queue)
            level_node = []
            for i in range(0,length):
                cur = queue.pop(0)
                level_node.append(cur)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            for i in range(0,length):
                if i==length-1:
                    level_node[i].next=None
                else:
                    level_node[i].next=level_node[i+1]
        return root

8、116.填充每个节点的下⼀个右侧节点指针II(按层输出)

题⽬链接:https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/

该题描述如下:

image.png

该题需要注意的是理解题目,输入root,返回root,二叉树的存储结构要改变。

该题目本质上和上一道区别不大,可以直接使用上一道题的答案,但是这里我们给出一个改进版本。

C++版本:

Node* connect(Node* root) {
       if(root==NULL){
            return root;
        }
        queue<Node*> queue;
        queue.push(root);
        while(!queue.empty()){
            int size = queue.size();
            vector<Node*> level_node;//记录每层的node
            Node* pre;
            Node* cur;
            for(int i=0;i<size;i++){
                cur=queue.front();
                queue.pop();
                if(i!=0){
                    pre->next = cur;
                }
                pre= cur;
                if (cur->left!=NULL){
                    queue.push(cur->left);
                }
                if (cur->right!=NULL){
                    queue.push(cur->right);
                }
            }
        }
        return root; 
    }

Python版本:

def connect(self, root: 'Node') -> 'Node':
        if not root:
            return root
        queue = [root]
        while len(queue)>0:
            length = len(queue)
            pre = None
            cur = None
            for i in range(0,length):
                cur = queue.pop(0)
                if i!=0:
                    pre.next = cur
                pre = cur
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
        return root

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔法攻城狮MRL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值