Question: Implement Inorder Traversal iteratively.
My Attempt: (results in an infinite loop that I haven't been able to debug) any help or suggestions greatly appreciated
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
#include <vector>
#include <stack>
#include <unordered_set>
using namespace std;
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
//iterative sol:
vector<int> sol;
stack<TreeNode*> dfs;
dfs.push(root);
unordered_set<TreeNode*> visited;
visited.insert({root});
TreeNode* temp;
while (!dfs.empty()) {
if (dfs.top()->left != nullptr && visited.find(dfs.top()->left) == visited.end()) {
dfs.push(dfs.top()->left);
visited.insert({dfs.top()->left});
}
else {
sol.push_back(dfs.top()->val);
temp = dfs.top();
dfs.pop();
if (temp->right != nullptr && visited.find(temp->right) == visited.end()) {
dfs.push(temp->right);
visited.insert({temp->right});
}
}
}
return sol;
}
};
EDIT: I don't have the specific internal definitions of the TreeNode, but if you want to run the problem, checkout: https://leetcode.com/problems/binary-tree-inorder-traversal/
Here is the problem :
dfs.push(dfs.top()->left);
visited.insert(dfs.top()->left);
You are pushing to stack (then dfs.top() will change) and then accessing dfs.top()->left in the next line.
You are modifying the stack in the first line here
dfs.push(dfs.top()->left);
visited.insert({dfs.top()->left});
what you want to do is to mark the previous dfs.top()->left as visited, but you are adding more element on top of the stack and thus the new dfs.top() is a different one.
To solve this problem you should use store the previous dfs.top()->left in a different variable.
As a best practice, the variable or object you are working on should be immutable, since the stack is not immutable don't use its top while inserting into it or doing some other computations. Instead store your required variable into something immutatble like temp here
temp = dfs.top();
if (temp->left != nullptr && visited.find(temp->left) == visited.end()) {
dfs.push(temp->left);
visited.insert({temp->left});
}
else {
sol.push_back(dfs.top()->val);
dfs.pop();
if (temp->right != nullptr && visited.find(temp->right) == visited.end()) {
dfs.push(temp->right);
visited.insert({temp->right});
}
}
It only takes 2 simple rules to implement an iterative in-order traversal.
If you're at node X, then:
If X has a right child, then move to the right child, and follow as many left links as possible to find the next node.
Otherwise, find the closest ancestor of X on the right, i.e., the closest ancestor whose left subtree contains X. If there is no such ancestor then you're done.
If your tree doesn't have parent links, then you'll need a stack to store the right ancestors, but there's no need for a visited set:
vector<int> inorderTraversal(TreeNode* tree) {
vector<int> ret;
stack<TreeNode *> nextParents;
for(;tree; tree = tree.left) {
nextParents.push(tree);
}
while(!nextParents.empty()) {
tree = nextParents.pop();
ret.push_back(tree->val);
for(tree = tree.right; tree; tree = tree.left) {
nextParents.push(tree);
}
}
return ret;
}
Related
I am working on the LeetCode problem 102. Binary Tree Level Order Traversal:
Given the root of a binary tree, return the level order traversal of its nodes' values. (i.e., from left to right, level by level).
I want to print all nodes at a given level in one group. I have found a way to do this in this answer on Stack Overflow.
But this answer uses recursion while my code does not. I would like to know where I am going wrong in my approach.
For example given input : [1,2,3,4,null,null,5]
My output : [[1],[4],[5]]
Expected output: [[1],[2,3],[4,5]]
#include <iostream>
#include <vector>
#include <map>
#include <deque>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
vector<vector<int>> levelOrder(TreeNode *root) {
deque<TreeNode *> queue;
map<int, vector<int>> myMap;
vector<vector<int>> retvector;
vector<int> addvector;
int level = 0;
if (root != nullptr) {
queue.push_back(root);
addvector.push_back(root->val);
//retvector.push_back(addvector);
myMap.insert(pair<int, vector<int>>(level, addvector));
}
while (!queue.empty()) {
TreeNode *ptr = queue.front();
queue.pop_front();
addvector.clear();
if (ptr->left != nullptr) {
addvector.push_back(ptr->left->val);
queue.push_back(ptr->left);
}
if (ptr->right != nullptr) {
addvector.push_back(ptr->right->val);
queue.push_back(ptr->right);
}
if (!addvector.empty()) {
//retvector.push_back(addvector);
myMap.insert(pair<int, vector<int>>(level, addvector));
level++;
addvector.clear();
}
}
for (int i = 0; i < level; i++) {
retvector.push_back(myMap[i]);
}
return retvector;
}
int main() {
TreeNode root, left1, left2, right1, right2;
left2 = TreeNode(4);
left1 = TreeNode(2, &left2, nullptr);
right2 = TreeNode(5);
right1 = TreeNode(3, nullptr, &right2);
root = TreeNode(1, &left1, &right1);
vector<vector<int>> v = levelOrder(&root);
for (auto &i: v) {
for (auto &j: i)
cout << j << " ";
cout << endl;
}
}
You don't need a map, nor a queue, nor a level number.
Instead alternate with 2 vectors that have the nodes of 2 consecutive levels.
Also, in your logic, addvector can at the most have 2 entries, which shows why this approach cannot work.
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<TreeNode *> parentLevel, childLevel;
vector<vector<int>> retvector;
vector<int> addvector;
if (root != nullptr) {
parentLevel.push_back(root);
}
while (!parentLevel.empty()) {
addvector.clear();
childLevel.clear();
for (auto parent : parentLevel) {
addvector.push_back(parent->val);
if (parent->left != nullptr) {
childLevel.push_back(parent->left);
}
if (parent->right != nullptr) {
childLevel.push_back(parent->right);
}
}
retvector.push_back(addvector);
parentLevel = childLevel;
}
return retvector;
}
};
Explanation
Let's take the example tree:
1
/ \
2 3
/ \
4 5
parentLevel starts out with [1] (actually the TreeNode having 1).
Then the outer loop starts, where the inner loop will take every node in that parentLevel vector and put its value in addvector. So in this iteration, addvector will be [1].
In the same process all direct children of these nodes are collected in childLevel, so there we will have the nodes [2, 3].
The inner loop then finishes, and addvector is appended to the result. So retvector will be [[1]].
Now the same should happen with the children, so we promote childLevel to be the parentLevel for the next iteration of the outer loop.
And so we start the next iteration of the outer loop with parentLevel having [2, 3]. Again, the corresponding values get pushed to an empty addvector, which will then have [2, 3]. At the same time childLevel gets populated with the child nodes [4, 5].
The second iteration of the outer loop will end by extending retvector to [[1],[2,3]], and so the process continues level by level...
So there is a question in Leetcode in which we need to tell whether two binary trees are identical or not. So my function is working correctly for the inputs [1,2,3] and [1,2,3]
but it is printing 'true' for the inputs [1,2] and [1,NULL,2] instead of printing 'false'. Please can anyone tell me what have i done wrong in this program.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* enter code here TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution
{
public:
bool isSameTree(TreeNode *p, TreeNode *q)
{
if (p == NULL && q == NULL)
return true;
if (p != NULL && q != NULL)
{
if (p->val != q->val)
return false;
else
{
isSameTree(p->left, q->left);
isSameTree(p->right, q->right);
}
return true;
}
else
return false;
}
};
You're completely ignoring the results of those recursive calls. The point using recursion here is that two trees are the same if:
Their values are the same AND
Their respective children are the same.
You're testing the former, but never reaping the results of the latter. In reality, what you really should be trying to do is this:
class Solution
{
public:
bool isSameTree(const TreeNode *p, const TreeNode *q)
{
if (p == q) // same actual tree or both NULL
return true;
if (p != NULL && q != NULL)
{
return p->val == q->val &&
isSameTree(p->left, q->left) &&
isSameTree(p->right, q->right);
}
return false;
}
};
I am stuck on a Huffman Tree problem. I think my code has a clear logic. I first built a priority queue to compare the weight of Node and place the Node with minimum weight at the top of the priority queue.
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct Node
{
int weight, depth;
Node *left, *right;
Node(int value):weight(value), left(NULL),right(NULL),depth(0){}
Node(int value, Node* left_leaf_ptr, Node* right_leaf_ptr) : weight(value), left(left_leaf_ptr), right(right_leaf_ptr), depth(0) {}
};
//this struct is used for priority queue
struct Greater
{
bool operator () (Node a, Node b){return a.weight > b.weight;}
};
// find whether the node is a leaf
bool isleaf(Node node) { return node.left == NULL && node.right == NULL; }
// update the depth of Huffman Tree
void update_depth(Node& node,int depth)
{
node.depth=depth;
if (! isleaf(node))
{
depth++;
update_depth(*node.left,depth);
update_depth(*node.right, depth);
}
}
Node build_Huffman_tree(priority_queue<Node, vector<Node>, Greater> weights_queue)
{
while (weights_queue.size() > 1)
{
Node l1=weights_queue.top();
weights_queue.pop();
Node l2 = weights_queue.top();
weights_queue.pop();
Node l3(l1.weight + l2.weight, &l1, &l2);
update_depth(l3, 0);
weights_queue.push(l3);
}
return weights_queue.top();
}
int main()
{
priority_queue<Node, vector<Node>, Greater> weights_queue;
weights_queue.push(Node(1));
weights_queue.push(Node(1));
weights_queue.push(Node(3));
weights_queue.push(Node(5));
Node root = build_Huffman_tree(weights_queue);
return 0;
}
When I run this program in C++ 11, in the second while loop inside the function build_Huffman_tree, it creates a Node of weight 2, depth 4700. What's worse is that this Node seems endless. i.e. its left child tree has weight 2, and this child tree has its left child tree of weight 2, and so on...
So please point out the reason of my program's failure and teach me how to fix it.
I'm currently working on a C++ project and part of it is to traverse the binary tree using inorder, preorder, and postorder.
class TNode
{
public:
int val;
TNode() {}
TNode(int v) { val = v; }
TNode * left;
TNode * right;
TNode * parent;
};
class BTree
{
void print_pre_order(TNode *r);// print the node as you traverse according to the order.
void print_in_order();
void print_post_order();
}
BTree::BTree()
{
root = new TNode(1);
root->parent = 0;
root->left = new TNode(2);
root->right = new TNode(3);
root->left->left = new TNode(4);
root->left->right = new TNode (5);
root->right->left = new TNode(6);
}
void BTree::print_pre_order(TNode *r)
{
if (r == 0)
{
return;
}
cout << r->val;
print_pre_order(r->left);
print_pre_order(r->right);
}
int main()
{
BTree y;
y.print_pre_order(y.root);
return 0;
}
In my default constructor, I've initialized values for some nodes, but when I run the code, the output I'm getting is "124" and gets an error. I don't know where I did wrong, can someone help?
I see no signs that the program ever sets any any pointers to zero, so if (r == 0) is unlikely to ever trigger an exit.
Give this a try:
class TNode
{
public:
int val;
TNode(): val(0), left(nullptr), right(nullptr), parent(nullptr) {}
TNode(int v): val(v), left(nullptr), right(nullptr), parent(nullptr) {}
TNode * left;
TNode * right;
TNode * parent;
};
The : tells the compiler that a member initializer list is coming. After that the code initializes all of the pointer members to point at null.
Change the
if (r == 0)
to
if (r == nullptr)
to better convey intent and you should be good to go.
This seems like it should be really easy but I've been having trouble with this for quite some time. As the title says, I'm just trying to find the node in a Binary tree (not a BST!) with the smallest value and return it. I can write a recursive void function pretty easily that can at least assign the smallest value in the function, but I'm getting stuck on how to back track to previous nodes once I reach a NULL pointer.
I have a node class that has a pointer to a left and right child, each with its own value. Here is my (failed) attempt so far:
int preOrder(Node *node, int value, int count, int sizeOfTree)
{
count++; //keeps track of whether or not we have traversed the whole tree
if(value < node->getValue())
value = node->getValue();
if(count == sizeOfTree);
return value;
if(node == NULL)
//Want to return to the previous function call
//How do I do this for a non void function?
//for a void function, you could jsut type "return;" and the function
//back tracks to your previous place in the tree
//but since I'm returning a value, How would I go about doing this?
//these 2 calls are incorrect but the idea is that I first traverse the left subtree
//followed by a traversal of the right subtree.
preOrder(node->getLeft(), value);
preOrder(node->getRight(), value);
}
If possible, I would like to try and do this without keeping track of a "count" as well to make the code cleaner.
Let me know if anymore clarification is needed.
I don't really understand why, in your original code, you need to keep track of the amount of elements traversed. Here is my solution:
int find_min(Node* node)
{
int value = node->getValue()
Node* left_node = node->getLeft();
if (left_node != NULL)
{
int left_value = find_min(left_node);
if (left_value < value)
value = left_value;
}
Node* right_node = node->getRight();
if (right_node != NULL)
{
int right_value = find_min(right_node);
if (right_value < value)
value = right_value;
}
return value;
}
Basically what you need to do is just visit every node and keep track of the smallest value you've seen. This can actually be done fairly simply:
#include <algorithm>
#include <limits>
int preOrder(Node *node)
{
if(node == NULL) return std::numeric_limits<int>::max();
// this should never affect the calculation of the minimum
// (What could possibly be bigger than INT_MAX? At worst it's equal)
int value = std::min(
node->getValue(),
preOrder(node->getLeft())
);
value = std::min(
value,
preOrder(node->getRight())
);
return value;
}
OK, so you have an unordered binary tree and you're trying to find the lowest element in it.
Since the tree is unordered, the lowest element can be at any position in the tree, so you must search the entire tree.
The characteristics of the search will be as follows:
thorough (whole tree is searched)
recursive (rather than iterative, which would be really yucky)
base case: node is NULL
base outcome: maintain current value
Lets write it then:
#include <algorithm>
using namespace std;
int searchLowest(Node * node, int value = INT_MAX)
{
if (node == NULL) // base case
return value; // base outcome
// at this point, node must not be NULL
value = min(value, preOrder(node->getRight(), value)); // thorough, always recurse
value = min(value, preOrder(node->getLeft (), value)); // and check children
value = min(value, node->getValue());
return value;
}
Edit for thoroughness, justice, and OOness:
// Node.h
#include <algorithm>
using namespace std;
template <typename T>
class Node
{
public:
Node(T item)
{
data = item;
}
T lowest()
{
T value = data;
if (right != NULL)
value = min(value, right->lowest());
if (left != NULL)
value = min(value, left->lowest());
return value;
}
Node<T> * getRight()
{
return right;
}
Node<T> * getLeft()
{
return left;
}
private:
T data;
Node<T> * right;
Node<T> * left;
};
// main.cpp
#include <iostream>
#include "Node.h"
using namespace std;
int main(int c, char * v[])
{
Node<int> * tree = sycamore(); // makes a nice big tree
cout << tree->lowest();
}
SEE JIMMY RUN