N元树级遍历错误(C ++)

时间:2020-01-05 14:27:04

标签: c++ tree traversal

我正在对LeetCode进行编码挑战,并要求遍历每个级别,最后返回嵌套的向量,其中每个值都有值节点值。

所以,如果我有一棵像这样的树:

enter image description here

哪个

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

预期输出是

输出:[[1],[3,2,4],[5,6]]

节点的定义如下:

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

我正在尝试以下迭代解决方案:

class Solution {
public:
    vector<vector<int>> answer;
    stack<Node*> nodes;
    vector<vector<int>> levelOrder(Node* root) {
        if(root == NULL)
            return answer;
        nodes.push(root);
        answer.push_back(vector<int>() = {root->val});
        while(!nodes.empty())
        {
            Node* curr = nodes.top();
            nodes.pop();
            vector<int>temp;

            for(int i = 0; i < curr->children.size(); i++)
            {
                nodes.push(curr->children[i]);
                temp.push_back(curr->children[i]->val);
            }
            if(temp.size() != 0)
                answer.push_back(temp);
        }
        return answer;
    }
};

但是在第20个测试用例中,输入始终为:

[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]]

我的输出是

[[1],[2,3,4,5],[9,10],[13],[8],[12],[6,7],[11],[14]]

我很难在纸上可视化和绘制这棵N元树,因此我很难理解算法出了什么问题。

1 个答案:

答案 0 :(得分:0)

代码的问题在于,对于您访问的每个节点,都将其所有子节点作为新列表附加到答案列表中。您的代码不会像解决方案所期望的那样,将相同级别但具有不同父级的子级分组到一个列表中。

让我们逐步检查您的代码,看看会发生什么:

  • 在循环之前,将根节点压入堆栈,并将具有根节点值的单例集压入答案:

    stack = {1}
    answer = { {1} }
    
  • 第一次迭代从堆栈中弹出1。然后,您遍历被推入堆栈的子项2,3,4,5。然后,将孩子列表推送到答案列表。

    stack = {2,3,4,5}
    answer = { {1}, {2,3,4,5} }
    
  • 下一个迭代从堆栈中弹出5。然后,您遍历子项9、10。将它们推入堆栈。然后,将孩子列表推送到答案列表。

    stack = {2,3,4,9,10}
    answer = { {1}, {2,3,4,5}, {9, 10} }
    
  • 下一个迭代从堆栈中弹出10。它没有孩子,所以什么也没发生。

    stack = {2,3,4,9}
    answer = { {1}, {2,3,4,5}, {9, 10} }
    
  • 下一个迭代从堆栈中弹出9。然后,您遍历单个孩子13,将其压入堆栈。包含13个单例列表被推到答案集中。

    stack = {2,3,4}
    answer = { {1}, {2,3,4,5}, {9, 10}, {13} }
    
  • 下一个迭代从堆栈中弹出4。然后,您遍历被推入堆栈的单个子项8。包含8个单例列表被推到答案集中。

    stack = {2,3,8}
    answer = { {1}, {2,3,4,5}, {9, 10}, {13}, {8} }
    

    您可以从这里看到答案列表有误。 8与9和10处于同一级别,因此应该将其添加到答案列表的{9,10}子列表中,而不是创建新列表{8}。这应该足以说明问题,因此我将不进一步介绍代码。

为确保将同一级别的节点分组到答案列表中的同一子列表中,我们在访问每个节点时必须跟踪当前级别。我们可以通过扩展堆栈来容纳当前节点及其深度的对来实现。然后,深度为d的每个节点值将附加到答案列表中的第d子列表中。这样可以确保将同一级别上的节点分组到一个子列表中。

std::vector<std::vector<int>> get_vals_per_level(const Node *root) {

  std::vector<std::vector<int>> vals_per_level{};
  std::stack<std::pair<const Node *, int>> stack{};

  stack.emplace(root, 0);

  while (!stack.empty()) {
    auto [current, depth]{stack.top()};
    stack.pop();

    if (vals_per_level.size() == depth) {
      vals_per_level.emplace_back();
    }

    // Append node value to the answer list for the current depth
    vals_per_level[depth].push_back(current->val);

    auto& children{current->children};

    for (auto it{children.rbegin()}; it != children.rend(); it++) {
      stack.emplace(*it, depth + 1);
    }
  }

  return vals_per_level;
}

代码使用的是C ++ 17中的structured bindings