[Leetcode] 314. Binary Tree Vertical Order Traversal 解题报告

这篇博客详细介绍了LeetCode 314题——二叉树垂直遍历的解题过程。博主通过一个例子展示了如何利用BFS(广度优先搜索)来正确解决这个问题,指出使用DFS(深度优先搜索)可能导致同一竖直层节点顺序错误的问题,并给出了相应的正确代码实现。

题目

Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column).

If two nodes are in the same row and column, the order should be from left to right.

Examples:

  1. Given binary tree [3,9,20,null,null,15,7],
       3
      /\
     /  \
     9  20
        /\
       /  \
      15   7
    

    return its vertical order traversal as:

    [
      [9],
      [3,15],
      [20],
      [7]
    ]
    
  2. Given binary tree [3,9,8,4,0,1,7],
         3
        /\
       /  \
       9   8
      /\  /\
     /  \/  \
     4  01   7
    

    return its vertical order traversal as:

    [
      [4],
      [9],
      [3,0,1],
      [8],
      [7]
    ]
    
  3. Given binary tree [3,9,8,4,0,1,7,null,null,null,2,5] (0's right child is 2 and 1's left child is 5),
         3
        /\
       /  \
       9   8
      /\  /\
     /  \/  \
     4  01   7
        /\
       /  \
       5   2
    

    return its vertical order traversal as:

    [
      [4],
      [9,5],
      [3,0,1],
      [8,2],
      [7]
    ]

思路

这道题目的基本思路是比较明显的,即首先构造一个map,其key值为在竖直方向上的位置,value则是在该位置上的所有结点值。然后在遍历树的过程中填充该map。这道题目的一个坑就是:我开始用了DFS,但是后来发现会导致同一竖直层中元素的顺序不对(例如最后一个例子中的倒数第二行[8,2]用DFS会形成[2,8])。所以正确的解法是采用BFS。

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> verticalOrder(TreeNode* root) {
        if (root == NULL) {
            return {};
        }
        map<int, vector<int>> mp;
        vector<vector<int>> ret;
        queue<pair<TreeNode*, int>> q;
        q.push(make_pair(root, 0));
        while(!q.empty()) {
            TreeNode* node = q.front().first;
            int index = q.front().second;
            q.pop();
            mp[index].push_back(node->val);
            if(node->left) {
                q.push(make_pair(node->left, index - 1));
            }
            if(node->right) {
                q.push(make_pair(node->right, index + 1));
            }
        }
        for(auto it = mp.begin(); it != mp.end(); ++it) {
            ret.push_back(it->second);
        }
        return ret;
    }
};
使用队列(Queue)实现树(Tree)结构或相关遍历算法,主要体现在广度优先搜索(Breadth-First Search, BFS)中,尤其是在二叉树的层次遍历(Level Order Traversal)中。该方法通过队列来管理待访问的节点,确保每一层的节点按照从左到右的顺序依次被访问。 ### 层次遍历的基本思想 层次遍历是一种广度优先的方式,利用队列先进先出(FIFO)的特性来实现。具体步骤如下: 1. 将根节点入队。 2. 当队列不为空时,取出队首元素进行访问。 3. 将当前节点的左右子节点(如果存在)依次入队。 4. 重复步骤2和3,直到队列为空。 这种方法可以保证每层的节点按顺序被访问,是典型的广度优先遍历方式[^5]。 ### 使用队列实现层次遍历的代码示例(C语言) 以下是一个基于队列实现二叉树层次遍历的完整示例,包含队列的定义、初始化及操作函数,以及二叉树的构建与层次遍历函数。 #### 队列的定义与操作 ```c // queue.h #pragma once #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <stdbool.h> typedef struct BinaryTreeNode* QDataType; typedef struct QueueNode { struct QueueNode* next; QDataType data; } QNode; typedef struct Queue { QNode* head; QNode* tail; int size; } Que; void QueueInit(Que* pq); void QueueDestroy(Que* pq); void QueuePush(Que* pq, QDataType x); void QueuePop(Que* pq); QDataType QueueFront(Que* pq); QDataType QueueBack(Que* pq); bool QueueEmpty(Que* pq); int QueueSize(Que* pq); ``` ```c // queue.c #include "queue.h" void QueueInit(Que* pq) { assert(pq); pq->head = pq->tail = NULL; pq->size = 0; } void QueueDestroy(Que* pq) { assert(pq); QNode* cur = pq->head; while (cur) { QNode* next = cur->next; free(cur); cur = next; } pq->head = pq->tail = NULL; pq->size = 0; } void QueuePush(Que* pq, QDataType x) { assert(pq); QNode* newnode = (QNode*)malloc(sizeof(QNode)); if (newnode == NULL) { perror("malloc fail"); exit(EXIT_FAILURE); } newnode->data = x; newnode->next = NULL; if (pq->tail == NULL) { pq->head = pq->tail = newnode; } else { pq->tail->next = newnode; pq->tail = newnode; } pq->size++; } void QueuePop(Que* pq) { assert(pq); assert(!QueueEmpty(pq)); QNode* del = pq->head; if (pq->head->next == NULL) { pq->head = pq->tail = NULL; } else { pq->head = pq->head->next; } free(del); pq->size--; } QDataType QueueFront(Que* pq) { assert(pq); assert(!QueueEmpty(pq)); return pq->head->data; } QDataType QueueBack(Que* pq) { assert(pq); assert(!QueueEmpty(pq)); return pq->tail->data; } bool QueueEmpty(Que* pq) { assert(pq); return pq->size == 0; } int QueueSize(Que* pq) { assert(pq); return pq->size; } ``` #### 二叉树的定义与层次遍历 ```c // binary_tree.h #include "queue.h" typedef char BTDataType; typedef struct BinaryTreeNode { BTDataType data; struct BinaryTreeNode* left; struct BinaryTreeNode* right; } BTNode; BTNode* CreateBinaryTree(char* array, int* index, int size); void LevelOrderTraversal(BTNode* root); ``` ```c // binary_tree.c #include "binary_tree.h" #include <stdio.h> #include <stdlib.h> BTNode* BuyNode(BTDataType data) { BTNode* node = (BTNode*)malloc(sizeof(BTNode)); if (!node) { perror("malloc failed"); exit(EXIT_FAILURE); } node->data = data; node->left = node->right = NULL; return node; } BTNode* CreateBinaryTree(char* array, int* index, int size) { if (*index >= size || array[*index] == '#') { (*index)++; return NULL; } BTNode* root = BuyNode(array[(*index)++]); root->left = CreateBinaryTree(array, index, size); root->right = CreateBinaryTree(array, index, size); return root; } void LevelOrderTraversal(BTNode* root) { if (root == NULL) return; Que q; QueueInit(&q); QueuePush(&q, root); while (!QueueEmpty(&q)) { BTNode* current = QueueFront(&q); QueuePop(&q); printf("%c ", current->data); if (current->left != NULL) QueuePush(&q, current->left); if (current->right != NULL) QueuePush(&q, current->right); } QueueDestroy(&q); } ``` ```c // main.c #include "binary_tree.h" #include <stdio.h> int main() { char treeData[] = {'A', 'B', 'D', '#', '#', 'E', '#', '#', 'C', '#', 'F'}; int index = 0; int size = sizeof(treeData) / sizeof(treeData[0]); BTNode* root = CreateBinaryTree(treeData, &index, size); printf("Level Order Traversal: "); LevelOrderTraversal(root); return 0; } ``` ### 总结 上述代码展示了如何使用队列实现二叉树的层次遍历。首先定义了队列的数据结构及其基本操作,然后实现了二叉树的创建和层次遍历功能。通过队列,可以有效地控制节点的访问顺序,从而实现广度优先的遍历策略。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值