Home > Enterprise >  Preorder traversal of binary tree
Preorder traversal of binary tree

Time:01-10

Ques - Given the root of a binary tree, return the preorder traversal of its nodes' values. Link Here

I am solving this question by recursion approach . Given below is my code

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        if(root)
        {
            ans.push_back( root -> val);
            preorderTraversal(root ->left);
            preorderTraversal(root ->right);
        }
        return ans;
    }
};

All the test cases are passed except one i.e [1,null,2,3]. But when I declare vector<int> ans before vector<int> preorderTraversal(TreeNode* root) the test case gives correct output. I want to know why this happens.

CodePudding user response:

The ans variable is not shared among function calls, and you discard the result from the recursions, so you can add at most one element to the result.

Delegating to a helper function is a common solution that avoids copying and manual state management:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        traverse(root, ans);
        return ans;
    }
private:
    void traverse(const TreeNode* root, vector<int>& ans) const
    {
        if(root)
        {
            ans.push_back(root->val);
            traverse(root->left, ans);
            traverse(root->right, ans);
        }
    }
};

CodePudding user response:

The problem is that you ignore the return values from the recursive calls to preorderTraversal. Therefore your method will ever return maximum 1 value - the value of the root node.

A simple solution for your current code would be to store the result of the resursive call in a variable and append the elements to ans:

ans.push_back( root -> val);
auto l = preorderTraversal(root ->left);
ans.insert(ans.end(), l.begin(), l.end());
auto r = preorderTraversal(root ->right);
ans.insert(ans.end(), r.begin(), r.end());

This is not so efficient since the vectors from the recuresive calls are effectivly copied.

A more efficient approach would be to pass the result vector by reference to preorderTraversal (it should be created empty before calling it for the root). Then preorderTraversal can add elements (including recursivly) to this result vector.

An alternative for passing the result by reference is storing it in a member variable of the class, as shown in the other answer.

CodePudding user response:

vector<int> ans; is a local variable that is destroyed after call to preorderTraversal. Apart from that, you are ignoring return values of your recursive calls. I think you want to keep your ans as a class field and populate it with recursive calls:

class Solution {
public:
    void preorderTraversal(TreeNode* root) {
        if(root)
        {
            _ans.push_back( root -> val);
            preorderTraversal(root ->left);
            preorderTraversal(root ->right);
        }
    }
private:
    std::vector<int> _ans;
};

Then of course you would need some accessors, a way to clear the results, etc. But I guess this is not the scope of your question.

  • Related