按层次遍历二叉树_107.二叉树的层次遍历 II

题目描述

给定一个二叉树,返回其节点值自底向上的层次遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

例如:
给定二叉树[3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其自底向上的层次遍历为:

[
  [15,7],
  [9,20],
  [3]
]

迭代实现

迭代遍历比较直观,就是按层遍历

98d262f7a493d4df07135e283d57f1af.png

我们将我们一层遍历得到的结果放到一个数组中,等这一层遍历完后,将这个数组放入到最终结果集res中。
因为题目要求是反序输出,所以我们只需将res翻转一下就可以了。

我们看下如何实现这个迭代遍历

2dccd43844a5fcc235380c2663c8534b.png

如上图,首先创建一个队列,将根节点root放入队列中,然后不断循环遍历这个队列。
对于树的第一层,其长度为1,而此时根节点也放到队列中了,所以队列的长度也是1,我们取出一个元素,将其放入临时数组中。
如果这个节点的左右孩子不为空,则将他们也放入队列中。

6fcf0f75ecd76c06ea3a55055d989667.png

上图是处理第二层的过程,类似于第一层,由于第一层遍历完后,队列里有两个元素了,所以第二次遍历的时候,可以确定队列长度是2,于是执行两次,将23取出,放入临时数组中,之后再将23的两个孩子也放入队列中。
处理第三层时,队列长度就是4了,于是取出4个元素,再次处理。

java代码:

class Solution {
    public List> levelOrderBottom(TreeNode root) {if(root==null) {return new ArrayList>();
        }//用来存放最终结果
        ArrayList> res = new ArrayList>();//创建一个队列,将根节点放入其中
        Queue queue = new LinkedList();
        queue.offer(root);while(!queue.isEmpty()) {//每次遍历的数量为队列的长度int size = queue.size();
            ArrayList tmp = new ArrayList();//将这一层的元素全部取出,放入到临时数组中,如果节点的左右孩子不为空,继续放入队列for(int i=0;i                TreeNode node = queue.poll();
                tmp.add(node.val);if(node.left!=null) {
                    queue.offer(node.left);
                }if(node.right!=null) {
                    queue.offer(node.right);
                }
            }
            res.add(tmp);
        }//翻转最终结果并返回
        Collections.reverse(res);return res;
    }
}

python代码:

class Solution(object):
    def levelOrderBottom(self, root):
        if not root:
            return []
        # 创建一个队列,将根节点放入其中    
        queue = [root]
        # 用来存放最终结果
        res = []
        while queue:
            # 每次遍历的数量为队列的长度
            size = len(queue)
            tmp = []
            # 将这一层的元素全部取出,放入到临时数组中,如果节点的左右孩子不为空,继续放入队列
            for _ in xrange(size):
                node = queue.pop(0)
                tmp.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            res.append(tmp)
        # 翻转最终结果并返回
        return res[::-1]

迭代实现-2

第一种方式中,我们将最终结果集定义成数组,等所有元素都放置完后,再翻转一下数组。
我们可以将最终结果集改成链表,以后每层遍历完将结果放入到链表的第一位,这样就自动完成了翻转的功能了。

java代码:

class Solution {
    public List> levelOrderBottom(TreeNode root) {if(root==null) {return new ArrayList>();
        }//改用链表实现,每次都插入到第一位
        LinkedList> res = new LinkedList>();
        Queue queue = new LinkedList();
        queue.offer(root);while(!queue.isEmpty()) {int size = queue.size();
            ArrayList tmp = new ArrayList();for(int i=0;i                TreeNode node = queue.poll();
                tmp.add(node.val);if(node.left!=null) {
                    queue.offer(node.left);
                }if(node.right!=null) {
                    queue.offer(node.right);
                }
            }//每次都保存到链表的第一位,这样自带了翻转的功能
            res.add(0,tmp);
        }return res;
    }
}

python代码:

class Solution(object):
    def levelOrderBottom(self, root):
        if not root:
            return []
        queue = [root]
        # 改用双端队列实现,每次都插入到第一位
        res = collections.deque()
        while queue:
            size = len(queue)
            tmp = []
            for _ in xrange(size):
                node = queue.pop(0)
                tmp.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            # 每次插入到第一位,这样自带了翻转的功能       
            res.appendleft(tmp)
        return list(res)

递归实现

递归实现就不那么直观了,我们可以把二叉树结构改变一下,想象成一个三角形的结构 我们在递归遍历时,将第一层的元素放入到第一层的数组中,将第二层的的元素放入到第二层,第三层的元素放入第三层。第三层的4是在5之前被遍历的,所以放入到第三层数组时,4就在5前面,同理6是在7前面被遍历的,所以放入到第三层时6就在7前面。

6cdcb3d4a9642f7a33a1c73cc652d051.png

这次我们不用创建队列了,直接在最终结果集res上操作,res是个二维数组,集合中嵌套集合,但现在没有任何嵌套的集合。

9eac422f88b0d31cf73ba3065a8f82a6.png

如上图所示,一开始res是空的,当遍历到第一层时候,我们创建一个集合,放入res,然后将第一层的1,放到res[0]中。
遍历到第二层时,再创建一个集合放入res,然后将2放入res[1]中。
遍历到第三层时,同样再创建一个集合放入res,将4放入res[2]中。
当我们再回到第三层,遍历到5时,就不用再创建新集合了,直接将5放到到res[2]中即可。
之后,再将3放到res[1]67放入res[2]中。

完整的遍历过程如下图:

737eb46606cd811aa1f9dccf5cf58ddd.gif

java代码:

class Solution {
    public List> levelOrderBottom(TreeNode root) {if(root==null) {return new ArrayList>();
        }//用来存放最终结果
        ArrayList> res = new ArrayList>();
        dfs(root,res,1);
        Collections.reverse(res);return res;
    }private void dfs(TreeNode root,ArrayList> res,int index) {if(root==null) {return;
        }//如果index大于res大小,说明这一层没有对应的集合,需要新创建if(index>res.size()) {
            res.add(new ArrayList());
        }//将当前层的元素直接放到对应层的末尾即可
        res.get(index-1).add(root.val);//继续遍历左右节点,同时将层高+1
        dfs(root.left,res,index+1);
        dfs(root.right,res,index+1);
    }
}

python代码:

class Solution(object):
    def levelOrderBottom(self, root):
        if not root:
            return []
        # 用来存放最终结果    
        res = []
        def dfs(root,index):
            if not root:
                return
            # 如果index大于res大小,说明这一层没有对应的集合,需要新创建    
            if index>len(res):
                res.append([])
            # 将当前层的元素直接放到对应层的末尾即可    
            res[index-1].append(root.val)
            # 继续遍历左右节点,同时将层高+1
            dfs(root.left,index+1)
            dfs(root.right,index+1)
        dfs(root,1)
        return res[::-1]
如果觉得不错又懒得留言 你可以点个在看7f1a92486a7a0585c32eca91c4ea4c40.png7f1a92486a7a0585c32eca91c4ea4c40.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是 C 语言按层遍历二叉树的代码,供您参考: ``` #include <stdio.h> #include <stdlib.h> struct TreeNode { int data; struct TreeNode *left; struct TreeNode *right; }; struct QueueNode { struct TreeNode *node; struct QueueNode *next; }; void level_order_traversal(struct TreeNode *root) { if (root == NULL) { return; } // 创建队列 struct QueueNode *front = NULL; struct QueueNode *rear = NULL; // 根节点入队 struct QueueNode *node = (struct QueueNode *) malloc(sizeof(struct QueueNode)); node->node = root; node->next = NULL; front = node; rear = node; // 不断遍历队列 while (front != NULL) { // 取出队首节点 struct TreeNode *current_node = front->node; front = front->next; free(node); // 输出该节点的值 printf("%d ", current_node->data); // 如果有左子节点,入队 if (current_node->left != NULL) { node = (struct QueueNode *) malloc(sizeof(struct QueueNode)); node->node = current_node->left; node->next = NULL; rear->next = node; rear = node; } // 如果有右子节点,入队 if (current_node->right != NULL) { node = (struct QueueNode *) malloc(sizeof(struct QueueNode)); node->node = current_node->right; node->next = NULL; rear->next = node; rear = node; } } } // 测试 int main() { // 构建二叉树 struct TreeNode node1 = {1, NULL, NULL}; struct TreeNode node2 = {2, NULL, NULL}; struct TreeNode node3 = {3, NULL, NULL}; struct TreeNode node4 = {4, NULL, NULL}; struct TreeNode node5 = {5, NULL, NULL}; struct TreeNode node6 = {6, NULL, NULL}; struct TreeNode node7 = {7, NULL, NULL}; node1.left = &node2; node1.right = &node3; node2.left = &node4; node2.right = &node5; node3.left = &node6; node3.right = &node7; // 按层遍历二叉树 level_order_traversal(&node1); return 0; } ``` 注意,如果您有任何关于该代码的疑问或需求,请随时告诉我,我将竭诚为您服务。 ### 回答2: 按层遍历二叉树是一种广度优先搜索的方法,可以使用队列来实现。下面是C语言实现按层遍历二叉树的代码: ```c #include <stdio.h> #include <stdlib.h> // 二叉树节点结构体 typedef struct Node { int data; // 节点数据 struct Node* left; // 左子节点指针 struct Node* right; // 右子节点指针 } Node; // 创建新节点 Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); // 分配内存空间 newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; } // 按层遍历二叉树 void levelOrderTraversal(Node* root) { if (root == NULL) return; // 创建队列,并将根节点入队 Node** queue = (Node**)malloc(sizeof(Node*)); int front = 0; // 队列头指针 int rear = 0; // 队列尾指针 queue[rear++] = root; while (front < rear) { Node* current = queue[front++]; // 出队队首元素 // 访问当前节点 printf("%d ", current->data); // 将当前节点的左右子节点入队 if (current->left != NULL) queue[rear++] = current->left; if (current->right != NULL) queue[rear++] = current->right; } // 释放队列内存空间 free(queue); } int main() { // 创建示例二叉树 Node* root = createNode(1); root->left = createNode(2); root->right = createNode(3); root->left->left = createNode(4); root->left->right = createNode(5); // 按层遍历二叉树 printf("按层遍历二叉树结果:"); levelOrderTraversal(root); return 0; } ``` 上述代码中,首先定义了二叉树节点的结构体,包含节点数据、左子节点指针和右子节点指针。然后,定义了用于创建新节点的函数`createNode()`。接下来,定义了按层遍历二叉树的函数`levelOrderTraversal()`。在该函数中,创建了一个队列并将根节点入队,然后进行循环操作直到队列为空。在每一轮循环中,首先将队首元素出队并访问,然后将其左右子节点入队。最后,在主函数中创建了示例二叉树并调用`levelOrderTraversal()`函数来按层遍历二叉树,并将结果打印输出。 ### 回答3: 按层遍历二叉树的代码可以使用队列来实现。首先将二叉树的根节点入队,然后开始循环,直到队列为空。在循环中,先取出队列的首个节点,访问该节点,并将其左右子节点分别入队。这样就可以保证按照层次遍历的顺序依次访问二叉树的每个节点。 下面是C语言实现按层遍历二叉树的代码: ```c #include <stdio.h> #include <stdlib.h> // 二叉树节点的定义 typedef struct Node { int data; struct Node* left; struct Node* right; } Node; // 创建新节点 Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); if (newNode == NULL) { printf("内存分配失败"); exit(1); } newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; } // 按层遍历二叉树 void levelOrderTraversal(Node* root) { // 创建一个队列用于存储节点 Node* queue[100]; int front = 0; // 队列的头指针 int rear = 0; // 队列的尾指针 // 根节点入队 queue[rear++] = root; while (front < rear) { Node* current = queue[front++]; printf("%d ", current->data); // 左右子节点入队 if (current->left != NULL) { queue[rear++] = current->left; } if (current->right != NULL) { queue[rear++] = current->right; } } } int main() { // 创建二叉树 Node* root = createNode(1); root->left = createNode(2); root->right = createNode(3); root->left->left = createNode(4); root->left->right = createNode(5); root->right->left = createNode(6); root->right->right = createNode(7); // 按层遍历二叉树 printf("按层遍历二叉树结果:"); levelOrderTraversal(root); return 0; } ``` 以上代码首先创建了一个二叉树,并使用`levelOrderTraversal`函数按照层次遍历的顺序输出二叉树节点的值。最后运行程序即可得到按层遍历二叉树的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值