printing all binary trees from inorder traversal - c++

Came across this question in an interview.
Given inorder traversal of a binary tree. Print all the possible binary trees from it.
Initial thought:
If say we have only 2 elements in the array. Say 2,1.
Then two possible trees are
2
\
1
1
/
2
If 3 elements Say, 2,1,4. Then we have 5 possible trees.
2 1 4 2 4
\ / \ / \ /
1 2 4 1 4 2
\ / / \
4 2 1 1
So, basically if we have n elements, then we have n-1 branches (childs, / or ).
We can arrange these n-1 branches in any order.
For n=3, n-1 = 2. So, we have 2 branches.
We can arrange the 2 branches in these ways:
/ \ \ / /\
/ \ / \
Initial attempt:
struct node *findTree(int *A,int l,int h)
{
node *root = NULL;
if(h < l)
return NULL;
for(int i=l;i<h;i++)
{
root = newNode(A[i]);
root->left = findTree(A,l,i-1);
root->right = findTree(A,i+1,h);
printTree(root);
cout<<endl;
}
}

This problem breaks down quite nicely into subproblems. Given an inorder traversal, after choosing a root we know that everything before that is the left subtree and everthing after is the right subtree (either is possibly empty).
So to enumerate all possible trees, we just try all possible values for the root and recursively solve for the left & right subtrees (the number of such trees grows quite quickly though!)
antonakos provided code that shows how to do this, though that solution may use more memory than desirable. That could be addressed by adding more state to the recursion so it doesn't have to save lists of the answers for the left & right and combine them at the end; instead nesting these processes, and printing each tree as it is found.

I'd write one function for constructing the trees and another for printing them.
The construction of the trees goes like this:
#include <vector>
#include <iostream>
#include <boost/foreach.hpp>
struct Tree {
int value;
Tree* left;
Tree* right;
Tree(int value, Tree* left, Tree* right) :
value(value), left(left), right(right) {}
};
typedef std::vector<Tree*> Seq;
Seq all_trees(const std::vector<int>& xs, int from, int to)
{
Seq result;
if (from >= to) result.push_back(0);
else {
for (int i = from; i < to; i++) {
const Seq left = all_trees(xs, from, i);
const Seq right = all_trees(xs, i + 1, to);
BOOST_FOREACH(Tree* tl, left) {
BOOST_FOREACH(Tree* tr, right) {
result.push_back(new Tree(xs[i], tl, tr));
}
}
}
}
return result;
}
Seq all_trees(const std::vector<int>& xs)
{
return all_trees(xs, 0, (int)xs.size());
}
Observe that for root value there are multiple trees that be constructed from the values to the left and the right of the root value. All combinations of these left and right trees are included.
Writing the pretty-printer is left as an exercise (a boring one), but we can test that the function indeed constructs the expected number of trees:
int main()
{
const std::vector<int> xs(3, 0); // 3 values gives 5 trees.
const Seq result = all_trees(xs);
std::cout << "Number of trees: " << result.size() << "\n";
}

Related

How to implement BST functions insert() and split() based upon rank?

I am trying to figure out how to implement code to the functions of insert() (which inserts an element into the tree), split() (which splits the tree on rank r into two trees of L and R. L containing ranks < r and R containing ranks >= r. For this assignment, I am dumbfounded. I believe I have the code for my insert correct for it works:
Node *insert(Node *T, int v, int r)
{
if(T == nullptr)
{
return new Node(v);
}
int rank = T->left ? T->left->size : 0;
if (r <= rank)
{
T -> left = insert(T -> left, v, rank);
}
else
{
T -> left = insert(T -> left, v, r - rank - 1);
}
fix_size(T);
return T;
}
For my split() function, I barely have anything that works. Can someone explain the algorithm of how to complete these two functions? Thank you!
I'm assuming we're dealing with unbalanced BSTs here (balance makes this harder).
Splitting the null tree is trivial (return (null, null)).
Given a non-null tree T, compare the rank of the root to r. If it's less, then recursively split the right child to get (R<, R≥) and return (T′, R≥) where T′ is T with the right child of the root replaced by R<. Similarity, if the rank of the root is greater than or equal to r, then recursively split the left child into (L<, L≥) and return (L<, T′′) where T′′ is T with the left child of the root replaced by L≥.
This has a slick iterative implementation with Node** pointers that I will leave as an exercise.

Counting the number of nodes in a level of a binary search tree

Like the title says, I want to count the nodes in for any given level of the tree. I already know how to make member functions for counting all the nodes of the tree, just not sure how to approach a specific level. Here's what I've tried. Any help is appreciated.
First parameter is a point to a character array inputted by the user. root is a private variable representing the "oldest" node.
int TreeType::GetNodesAtLevel(ItemType* itemArray, int level)
{
TreeNode* p = root;
if (itemArray == NULL)
return;
if (level == 0)
{
cout << p->info << " ";
return;
}
else
{
GetNodesAtLevel(itemarray->left, level); //dereference in one and not the other was just testing
GetNodesAtLevel(*itemarray->right, level); //neither seems to work
}
}
The way to do it is by using a queue (employing level order traversal - BFS). Now follow this:
Take two variables, count_level and count_queue (keeping total nodes in a queue).
for a tree like this:
A
/ \
B C
/ \ \
K L D
/
E
initially count_level = 0 and count_queue = 0. Now:
Add a node to the queue(at this point A, increment count_queue to 1).
Now when you find count_level = 0 do this -> count_level = count_queue.
Add the kid nodes while dequeuing till the count_level becomes 0. So at this point the follow step 2 and that will give you the no of nodes at level beneath what just has been processed.

Appropriate data structure for add and find queries

I have two types of queries.
1 X Y
Add element X ,Y times in the collection.
2 N
Number of queries < 5 * 10^5
X < 10^9
Y < 10^9
Find Nth element in the sorted collection.
I tried STL set but it did not work.
I think we need balanced tree with each node containing two data values.
First value will be element X. And another will be prefix sum of all the Ys of elements smaller than or equal to value.
When we are adding element X find preprocessor of that first value.Add second value associated with preprocessor to Y.
When finding Nth element. Search in tree(second value) for value immediately lower than N.
How to efficiently implement this data structure ?
This can easily be done using segment tree data structure with complexity of O(Q*log(10^9))
We should use so called "sparse" segment tree so that we only create nodes when needed, instead of creating all nodes.
In every node we will save count of elements in range [L, R]
Now additions of some element y times can easily be done by traversing segment tree from root to leaf and updating the values (also creating nodes that do not exist yet).
Since the height of segment tree is logarithmic this takes log N time where N is our initial interval length (10^9)
Finding k-th element can easily be done using binary search on segment tree, since on every node we know the count of elements in some range, we can use this information to traverse left or right to the element which contains the k-th
Sample code (C++):
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int sz = 31*4*5*100000;
ll seg[sz];
int L[sz],R[sz];
int nxt = 2;
void IncNode(int c, int l, int r, int idx, int val)
{
if(l==r)
{
seg[c]+=val;
return;
}
int m = (l+r)/2;
if(idx <= m)
{
if(!L[c])L[c]=nxt++;
IncNode(L[c],l,m,idx,val);
}
else
{
if(!R[c])R[c]=nxt++;
IncNode(R[c],m+1,r,idx,val);
}
seg[c] = seg[L[c]] + seg[R[c]];
}
int FindKth(int c, int l, int r, ll k)
{
if(l==r)return r;
int m = (l+r)/2;
if(seg[L[c]] >= k)return FindKth(L[c],l,m,k);
return FindKth(R[c],m+1,r,k-seg[L[c]]);
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int Q;
cin>>Q;
int L = 0, R = 1e9;
while(Q--)
{
int type;
cin>>type;
if(type==1)
{
int x,y;
cin>>x>>y;
IncNode(1,L,R,x,y);
}
else
{
int k;
cin>>k;
cout<<FindKth(1,L,R,k)<<"\n";
}
}
}
Maintaining a prefix sum in each node is not practical. It would mean that every time you add a new node, you have to update the prefix sum in every node succeeding it in the tree. Instead, you need to maintain subtree sums: each node should contain the sum of Y-values for its own key and the keys of all descendants. Maintaining subtree sums when the tree is updated should be straightforward.
When you answer a query of type 2, at each node, you would descend into the left subtree if N is less than or equal to the subtree sum value S of the left child (I'm assuming N is 1-indexed). Otherwise, subtract S + 1 from N and descend into the right subtree.
By the way, if the entire set of X values is known in advance, then instead of a balanced BST, you could use a range tree or a binary indexed tree.

Time complexity for this snippet

I am solving the following question from LeetCode.com:
Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).
For the tree:
3
/ \
9 20
/ \
15 7
The answer is:
[
[3],
[20,9],
[15,7]
]
I came up with the following code:
/**
* 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>> result;
void zigzagLevelOrderUtil(TreeNode* root, int level) {
if(root==NULL) return;
if(result.size()==level)
result.push_back(vector<int>());
result[level].push_back(root->val);
zigzagLevelOrderUtil(root->left, level+1);
zigzagLevelOrderUtil(root->right, level+1);
}
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
result.clear();
zigzagLevelOrderUtil(root, 0);
for(int i=0; i<result.size(); i++)
if(i%2!=0)
reverse(result[i].begin(), result[i].end()); //I think the complexity here is O(hn)
return result;
}
};
However, I am not sure about the complexity - is it O(hn) (where h is the height and n is the number of nodes); or is it just O(h). I am confused because technically, I am working (reversing) only on half of h; and I think it can have at max n/2 nodes. [Please see the comment in the code].
Could someone please confirm? Thanks!
Let's see.
Since there are h elements in result vector one can say the complexity is O(h.n) but in reality it is O(n).
Why is that? Because 'std::reverse' function has O(n) complexity. It seems like O(h.n) because you have h amount of vectors in result vector. But remember in total all that vectors have n elements which are the nodes of the tree.
Let's say we have a full binary tree with 3 levels including the root level. The result vector is something like [[x], [y, z], [t, w, m, n]]. 1 operation for result[0] and 1 for inner vector 0, 1 operation for result[1] and 2 for inner vector 1, 1 operation for result[2] and 4 for inner vector 2. So we have 10 operations which are equal to h+n operations. (For making our job easy, not only even indexes are processed but all of them are.)
As the inner vectors grow bigger the operation in which we go to the next index of outer vector is becoming insignificant. The time complexity is O(h+n) as seen in the example but h < n and so we can say it is O(n) complexity.

find sum of maximum possible triangular chord

I am having a binary tree
2
/ \
3 4
/ \ \
5 1 8
/ \ / \
1 6 9 2
\
4
i want to find the maximum possible triangular chord info sum of nodes ( between any two leaves and a node having both left and right child ) in the given tree.
a triangular chord will be
for triangular chord :
just imagine a line between any two leaves, go upward towards root, find a common parent (that can be parent, grandparent, grandgrandparent or even the root itself). While moving upwards, for each leaf ( for any leaf either we have to go upward only left left left .... and so OR either only right right right right .. and so) means ( left leaf will only move right upward only and right leaf will move left upward only..... So for any single leaf, we can not move in both direction while moving upwards).. Now we get a triangular shape.. in which a side may contain any no. of nodes/links possible.. NOW, if that triangular shape does not contain any extra internal branches. that triangular shape will be a triangular chord.
Do remember that every leaf node is also always a triangular chord (It is just to create the default cases if the binary tree do not have any triangular shaped chord)
now
maximum triangular chord will be that triangular chord
which have maximum total in sum of all its node info.
we are required to return that maximum total.
If we do not have triangular shaped chord..
then we have to return the leaf with maximum info.
for example
8
/ \
2 3
\
3
is a triangular chord
8
/ \
2 3
\ \
4 1
only subtree with single node 4 will be maximum triangular chord (as its sum is greater than another triangular chord with single node 1) Not the whole tree will be triangular chord
8
/ \
2 3
/ \
4 3
is a triangular chord
so the solution of the very first tree on the first line of question is
8+9+2+4 = 23
i am badly trapped in this problem.
I have a rough approach
I will recursively call leftchild as root of subtree and find the left maximum triangular chord sum
then same for rightchild as root of subtree.
add the max of leftmax and rightmax, and the add to rood node and return
in c++ mycode is :
int maxtri(node* n)
{
if(n)
{
lsum = maxtri(n->left);
rsum = maxtri(n->right);
k = maxof(lsum,rsum);
return (n->info + k);
}
}
edit : my another recursive approach
int l =0, r =0;
int maxtri(node* n)
{
if (n == NULL) return 0;
if (!(n->left) && !(n->right)) return n->info;
if ((n->left) && (n->right))
{
l = maxtri(n->left);
r = maxtri(n->right);
}
if ((n->left) && !(n->right))
{
l = l + maxtri(n->left);
}
if (!(n->left) && (n->right))
{
r = r + maxtri(n->right);
}
return (l+r+n->info);
}
i have doubt on my approach.
can anyone give another solution.??
What about this logic:
For each node traverse the left portion and right portion, if you find any branches then don't consider this node in your calculation else consider this. Moreover, for the part of calculation node should have left & right nodes or it should be leaf node.
Note: I have not tested it properly but i believe it should work.
// Node by Node traverse the tree
void addSum(Node *head, vector<int>& sum)
{
if (head == NULL)
return;
else {
int s = traverseThisNode(head);
sum.push_back(s); // Add to vector
addSum(head->left, sum);
addSum(head->right, sum);
}
}
// For each node traverse left & right
int traverseThisNode(Node *head)
{
if (head && head->left && head->right) {
Node *temp = head; // To traverse right portion of this node
int sum = head->value;
while(head->left) { // Traverse right
head = head->left;
sum = sum + head->value;
if (head->right) { // Condition to check if there is any branching
sum = 0;
break;
}
}
while(temp->right && sum != 0) { // Traverse Right now
temp = temp->right;
sum = sum + temp->value;
if (temp->left) { // Condition to check if there is any branching
sum = 0;
break;
}
}
return sum;
} else if (head && !head->left && !head->right) {
return head->value; // To add leaf node
}
return 0;
}
Now you have vector containing all the value of triangular in the tree, traverse it and
find the maximum.
int maximum()
{
// Traverse the vector "sum" & find the maximum
}
I write the pseudocode for my approach, as far as I have understood the question.
Max = min_value; //possibly 0 if no negative value is allowed for nodes.
sum = 0;
for each node in the tree
temp = node;
sum+= temp->data //collects data at the current level, the current level may be leaf too.
Until temp->left is not null, // Traversing uni-directionally to the left most deep and collecting data.
temp = temp->left
sum+=temp->data
Until temp->right is not null, // Traversing uni-directionally to the right most deep and collecting data.
temp = temp->right
sum+= temp->data
if(sum > Max)
Max = sum;
sum = 0;
print Max;