Reputation: 83
The path I'm getting is wrong - the recursion doesn't stop on the end condition. I have a tree node defined like this:
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
A tree:
And a function:
const getPath = function(root, node) {
let path = [];
const traverse = function(root, node) {
if (root.left || root.right) {
path.push(root.val);
}
if (root.val === node.val) {
path.push(root.val);
return;
}
if (root.left) {
traverse(root.left, node);
}
if (root.right) {
traverse(root.right, node);
}
};
traverse(root, node);
return path;
};
If I want to get the path to element 7
, the output would be [3, 5, 2, 7]
because that's the path from the root to that node.
But the output of my function is [3, 5, 2, 7, 1]
instead - it seems like it doesn't stop on the return condition but keeps going with whatever it has on a stack.
What's wrong with this code?
Example for the tree from my image:
const T = new TreeNode(3);
T.left = new TreeNode(5);
T.right = new TreeNode(1);
T.left.left = new TreeNode(6);
T.left.right = new TreeNode(2);
T.left.right.left = new TreeNode(7);
T.left.right.right = new TreeNode(4);
T.right.left = new TreeNode(0);
T.right.right = new TreeNode(8);
const node = T.left.right.left;
const path = getPath(T, node); // [3, 5, 2, 7, 1]
Upvotes: 0
Views: 1370
Reputation: 12990
You can keep track of whether or not you've found your node in another variable while doing a usual pre-order traversal. Based on whether or not you've found the node, you can append the current value to path
, or pop
if it wasn't found in any of the subtrees:
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
const getPath = function(root, node) {
let path = [];
let found = false;
const traverse = function(curr) {
if (!curr || found) return;
if (curr.val == node.val) found = true;
path.push(curr.val);
traverse(curr.left);
traverse(curr.right);
if (!found) path.pop();
};
traverse(root, node);
return path;
};
const T = new TreeNode(3);
T.left = new TreeNode(5);
T.right = new TreeNode(1);
T.left.left = new TreeNode(6);
T.left.right = new TreeNode(2);
T.left.right.left = new TreeNode(7);
T.left.right.right = new TreeNode(4);
T.right.left = new TreeNode(0);
T.right.right = new TreeNode(8);
console.log(getPath(T, T.left.right.left));
console.log(getPath(T, T.right.left));
console.log(getPath(T, T.left.left));
Upvotes: 0
Reputation: 371138
You should only push if the the left or right finds a match. (Right now, you're pushing unconditionally in the first if
.) One possibility is to create the array to return only when a match is found (that is, after recursion has found the match, and you're bubbling back up the tree and call stack):
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
const getPath = function(root, valToFind) {
if (root.val === valToFind) {
// found: create the array to return
return [root.val];
}
if (root.left) {
const result = getPath(root.left, valToFind);
if (result) {
// unshift: add this node's value to the beginning of the array
result.unshift(root.val);
return result;
}
}
if (root.right) {
const result = getPath(root.right, valToFind);
if (result) {
result.unshift(root.val);
return result;
}
}
};
const T = new TreeNode(3);
T.left = new TreeNode(5);
T.right = new TreeNode(1);
T.left.left = new TreeNode(6);
T.left.right = new TreeNode(2);
T.left.right.left = new TreeNode(7);
T.left.right.right = new TreeNode(4);
T.right.left = new TreeNode(0);
T.right.right = new TreeNode(8);
const node = T.left.right.left;
console.log(getPath(T, node.val)); // [3, 5, 2, 7]
console.log(getPath(T, 4));
console.log(getPath(T, 8));
console.log(getPath(T, 6));
Upvotes: 2