Code Which I have written for this :
sumBST(BST *root)
{
static sum =0;
if (root!= null)
{
if (root->left != null || root->right != null)
{
sum = sum + sumBST(root->left) + sumBST(root->right);
return sum;
}
else
{
root->data;
}
}
else
{
return 0;
}
return sum;
}
I have checked it by drawing recursion tree seems well but Still i am confused at some point I am doing some mistake. Please correct me i am doing something wrong here.
Well, it doesn't seem like you are actually adding the sum of the leaf nodes.
In parcticular - the line:
root->data
Does not actually return the data, just reads it.
Should be something like that in pseudo code:
sumBST(node):
if (root == null):
return 0
else if (root->left == null && root->right == null)
//add the value of the node if it is a leaf, this step is missing
return root->data;
else:
return sumBST(root->left) + sumBST(root->right)
EDIT:
The problem in the code are as follows (clarifying and explaining further that point in the answer):
You should return the data of the leaves somewhere - this is not happening anywhere in the code - I suspect you wanted to return it in root->data.
However note that the recursion will go to each and every leaf - it is just missing returning the value from each of them.
The purpose of such question is mainly focused on assessing the candidate thinking process.
All I see here is a typo error
root->data => return root->data
and an instruction that is never reached
return sum;
and one excessively long instruction
sum = sum + sumBST(root->left) + sumBST(root->right); => return sumBST(root->left) + sumBST(root->right);
Interviewers always like to get questioned about the problems they give.
A question like "Is the BST given or can I design a structure that is optimized toward given the sum of leaf?", "How big is the BST?"... Can add a plus and most likely change completely your answer.
Related
I need to find if all paths of a binary tree that can end(which means all paths that starts from the root and end to a node that has only one child or none) have lengths that differ by no more than one.
My working solution work like this: the function longestPath finds the longest path, the function checkLengths traverse all nodes keeping track of the length of the paths and every time a node with only one child or none is found it checks if the difference between the length of the current path and the length of the longest path is more than 1.
This solution has complexity O(2n) because at worst every node has to be visited twice, once for the longestPath function and once for the lengthCheck function. I would like to improve the solution to O(n) but I'm having an hard time figuring out how to do so.
Edit: my solution is still O(n) but I would like to optimize it to find the solution by visiting each node only once and not twice.
int lengthCheckFlag=1;
int maxLength=-1;
void longestPath(Node n,int currentLength){
if(n==nullptr){
return;
}
if(n->left==nullptr && n->right==nullptr){
if(maxLength==-1){
maxLength=currentLength;
}
else{
if(currentLength>maxLength){
maxLength=currentLength;
}
}
}
longestPath(n->left,currentLength+1);
longestPath(n->right,currentLength+1);
}
void checkLengths(Node n,int currentLength){
if(n==nullptr){
return;
}
if(n->left==nullptr || n->right==nullptr){
if(abs(maxLength-currentLength)>1){
lengthCheckFlag=0;
}
}
checkLengths(n->left,currentLength+1);
checkLengths(n->right,currentLength+1);
}
bool lengthCheckWrapper(Node n){
if(n==nullptr){
return true;
}
longestPath(n,0);
checkLengths(n,0);
return lengthCheckFlag;
}
Code Update:
int maxP=-1;
int minP=-1;
void minmaxPaths(Node n,int currentLength){
if(n==nullptr){
return;
}
if(n->left==nullptr && n->right==nullptr){
if(maxP==-1){
maxP=currentLength;
minP=currentLength;
}
else{
if(currentLength>maxP){
maxP=currentLength;
}
if(currentLength<minP){
minP=currentLength;
}
}
}
minmaxPaths(n->left,currentLength+1);
minmaxPaths(n->right,currentLength+1);
}
bool lengthCheckWrapper(Node n){
if(n==nullptr){
return true;
}
minmaxPaths(n,0);
if(abs(minP-maxP)<=1){
return true;
}
return false;
}
Some remarks:
O(2n) is the same as O(n)
Your functions use different conditions for identifying the potential end of a path: one uses a && operator (wrong) and the other uses a || operator (correct)
One idea for an alternative algorithm is to make a breadth first traveral. This is interesting, since the constraint really means that all non-perfect nodes (i.e. that have at most one child) must appear in the bottom two levels of the tree.
By consequence, if we find 2 more levels after the first level where we find a non-perfect node, then we have a violation and can stop the traversal.
The down side is that it uses more memory.
Here is how it could be implemented:
int minmaxDepth(Node root) {
if (root == nullptr) {
return 1; // OK
}
std::vector<Node> level, nextLevel;
level.push_back(root);
int minDepth = INT_MAX;
int currDepth = 0;
while (level.size()) {
currDepth++;
nextLevel = {};
for (auto & parent : level) {
if (currDepth < minDepth &&
(parent->left == nullptr || parent->right == nullptr)) {
minDepth = currDepth; // Found a path with minimal length
}
if (parent->left != nullptr) {
nextLevel.push_back(parent->left);
}
if (parent->right != nullptr) {
nextLevel.push_back(parent->right);
}
if (nextLevel.size() && currDepth > minDepth) {
return 0; // Paths have lengths that differ more than 1
}
}
level = nextLevel;
}
return 1; // All nodes were visited: no violation found
}
There is no need to pre-compute the longest path. Compute all path lengths and on the fly,
store the first length,
if some other length differs by more than one, you are done;
else store the differing length, and if any other length differs from the two stored ones, you are done.
I already implemented a method rankOfElement(x) in pseudocode which returns the rank for a given node x:
function rankofElement(x) {
rank = 0;
Node temp = root;
while (temp.key != x) {
if (x < temp.key) {
temp = temp.leftson
} else if (x > temp.key) {
rank += temp.leftson.size + 1;
temp = temp.rightson;
} else if (temp.key == x) {
return rank + temp.leftson.size
} else return "key not found"
}
Now I should implement a method (elementbyRank(k)) in pseudocode which returns a node with a specific rank k in the context of a binary tree.
I am struggling with that and I hope you can give me an answer.
So, if given rank k and we need to find a node with the given rank we first need a traversal algorithm to search through the tree. A pre-order traversal should work just fine. Here is a recursive one.
function preOrderTraversal(node){
if(node !== null){
print(node.data);
preOrderTraversal(node.left);
preOrderTraversal(node.right);
}
}
now that we have a way to get through our tree we need to implement the elementbyRank method and modify the traversal algorithm. Instead of printing the data we will check each node's rank. we will need to pass rank we need to find and we will need to add a return to the traversal.
The elementbyRank method is pretty simple:
function elementbyRank(k){
return preOrderTraversal(root, k);
}
Now we need to make the changes to the prePrderTraveral and let's change the name as well to elementbyRankTraversal.
function elementbyRankTraversal(node, key){
if(node !== null){
if(key == rankofElement(node.key))
return node;
return elementbyRankTraversal(node.left);
return elementbyRankTraversal(node.right);
}
return null;
}
So now if we find a node with the passed in rank, we will get that node back. but if one does not exist we will instead get a null value.
I know that you said given node x, the rankofElement(x) will return the rank of the element. but you are comparing the node's key directly to x which tell me that x is not a node but x is the key of node x. If I'm wrong then just remove the key part from elementbyRankTraversal().
And that should work.
Can we print a BST in level order without using a queue with O(n) time complexity? Below is a c++ code to do it in O(n^2) in worst case without a queue. I wonder whether we can achieve the same result in O(n). If not, can we at least improve this algorithm?
int height(Node* root) {
if (root==NULL) return -1;
int h1 = height(root->left);
int h2 = height(root->right);
return max(h1, h2) + 1;
}
void printLevel(Node* root, int level) {
if (!root) return;
if (level==0) {
cout << root->data << " ";
return;
}
printLevel(root->left, level - 1);
printLevel(root->right, level - 1);
}
void print(Node* root) {
int h=height(root);
for (int i = 0; i <= h ; i++) {
printLevel(root, i);
}
cout << endl;
}
Sure you can. You can maintain extra information in each node which points to:
the next item at this level if there is one; or
the first item at the next level otherwise.
This is superimposing a queue over the search tree, and it would look something like:
A > (B)
_/ \_
/ \
B > C > (D)
/ \ / \
D > E > F > G > (null)
Then it's a simple matter of following the different pointer chain to get breadth-first-search (BFS) order.
However, this is likely to complicate updates quite a bit and it will result in more storage being needed per node.
It's actually more efficient (space-wise) to use the queue method since your queue, unlike the extra pointers in the tree, will tend not to have all entries in it at once. In fact, it will never have elements in it from levels that are not directly adjacent.
By way of example, examine the classic code for BFS:
add root to queue
while queue is not empty:
get node from queue
do something with node
if node.left exists:
add it to queue
if node.right exists:
add it to queue
That's it, it really doesn't get any simpler than that. And the fact that you're reading an entry out of the queue before adding its children means that the storage requirements are less the the superimposed queue solution mentioned earlier.
Bottom line, when you find something as elegant and simple as the queue-based BFS algorithm, you want to think very hard before deciding to try a different approach.
Yes, we can do this, without using a queue, simply the concept is that, first explicitly print the first root node. And then check whether the right and left children are available or not. If so, print them and recursively apply for the next child nodes. This idea/code is only for void functions.
int num = 0;
void BFS_tree(struct BT *root){
if(root == NULL){
return;
}
if(num == 0){
printf("%d ", root->data);
num += 1;
}
if(root->left != NULL){
printf("%d ", root->left->data);
}
if(root->right != NULL){
printf("%d ", root->right->data);
}
BFS_tree(root->left);
BFS_tree(root->right);
}
I'm trying this question for sometime but couldn't figure out the algorithm. My preference is to do it iteratively. Till now, I've figure out something but not sure on some point.
Currently, My algorithm looks like:
First traverse the tree to find the node
While traversing the tree, keep track of the previous node.
if you find the node, check if left child is present then that is successor return.
if left child is not present then check if right child is present the that is successor and return.
if the node(is left to the parent) and don't have left or right child then we've saved the prev node earlier then either prev or prev's right child is the successor.
But what if the node we found is in the right to parent and don't have left or right child how to find successor of this node?
May be there are many flaws in this algorithm as still I've not understand all the cases properly. If anyone has any idea or algorithm please share.
Thanks in advance.
when you find a node in preorder, to find its successor is just travesing to its next node.
what I was thinking first is the relationship of a node and its successor's values in pre-oder, but I found that it seems not very clear like the relationship in in-order. I think there is only one step beteen a node and its successor(if exists) : just move on travesing. So I design this algorithm.
my algorithm below is based on preorder travesal, it can run on a binary tree,not only BST.
#define NOT_FOUND -1
#define NEXT 0
#define FOUND 1
struct node {
struct node *p;//parent,but useless here
struct node *l;//left child
struct node *r;//right child
int value;
};
int travese(struct node* bnode, int* flag,int value)
{
if(bnode == NULL)
return 0;
else
{
if(*flag == FOUND)
//when the successor is found,do pruning.
return 1;
else if(*flag == NEXT) {
printf("successor:%d\n",bnode->value);
*flag = FOUND;
return 1;
}
else if(*flag == NOT_FOUND && bnode->value == value)
*flag = NEXT;
travese(bnode->l,flag,value);
travese(bnode->r,flag,value);
}
return 0;
}
and use it by:
int flag = NOT_FOUND;
travese(root,&flag,value);
if(flag == NEXT || flag == NOT_FOUND)
printf("no successor.\n");
EDIT:
turning a recurrence algorithm to a iterative one is not difficult by using a stack like below:
int preorder_travese_with_stack(struct node* bnode, int* flag,int value)
{
if(bnode == NULL)
return 0;
struct stack s;//some kind of implement
push(s,bnode);
while(NotEmpty(s) && *flag) {
struct node *curNode = pop(s);
if(*flag == NEXT) {
printf("successor:%d\n",curNode->value);
*flag = FOUND;
return 1;
}
else if(*flag == NOT_FOUND && curNode->value == value)
*flag = NEXT;
push(s,curNode->r);
push(s,curNode->l);
}
return 0;
}
but according to your comment and original description, I think the one you want is iterative algorithm without a stack.here it is.
After thinking ,searching and trying, I wrote one. When travse the tree iteratively without stack , the parent of a node is not useless any more. In a path, some nodes is visited not only once, and you need to record its direction at that time.
int preorder_travese_without_stack(struct node *root,int value,int *flag)
{
int state=1;
//state: traveral direction on a node
//1 for going down
//2 for going up from its left chlid
//3 for going up from its right child
struct node *cur = root;
while(1) {
if(state == 1) //first visit
{
//common travese:
//printf("%d ",cur->value);
if(cur->value == value && *flag == NOT_FOUND)
*flag = NEXT;
else if (*flag==NEXT) {
*flag = FOUND;
printf("successor:%d\n",cur->value);
break;
}
}
if((state == 1)&&(cur->l!=NULL))
cur = cur->l;
else if((state==1)&&(cur->l==NULL))
{
state = 2;
continue;
}
else if(state==2) {
if(cur->r != NULL ) {
cur=cur->r;
state = 1;
}
else
{
if(cur->p!=NULL)
{
if(cur==cur->p->r)
state = 3;
//else state keeps 2
cur=cur->p;
}
else //cur->p==NULL
{
if(cur->p->r!=NULL)
{
cur=cur->p->r;
state = 1;
}
else
break;
//end up in lchild of root
//because root's rchild is NULL
}
}
continue;
}
else //state ==3
{
if(cur->p!=NULL)
{
if(cur==cur->p->l)
state = 2;
else
state = 3;
cur=cur->p;
continue;
}
else
break;
}
}
}
the usage is the same as the first recurrence one.
If you are confused yet,mostly about the direction of a node , you can draw a tree and draw the path of pre-order traverse on paper,it would help.
I'm not sure there are bugs left in the code,but it works well on the tree below:
0
/ \
1 2
/ \ / \
3 4 5 6
btw,"wirte down pre-order (or else) travese algorithm of a tree both by recurrence and iteration" is a common interview problem, although solving the latter by a stack is permitted.but I think the BST requirement is unnecessary in pre-order travese.
My implementation of the algorithm does not use the key. Therefore it is possible to use it in any kind of binary tree, not only in Binary search trees.
The algorith I used is this:
if given node is not present, return NULL
if node has left child, return left child
if node has right child, return right child
return right child of the closest ancestor whose right child is present and not yet processed
Bellow there is my solution.
TreeNode<ItemType>* CBinaryTree<ItemType>::succesorPreOrder(TreeNode<ItemType> *wStartNode)
{
//if given node is not present, return NULL
if (wStartNode == NULL) return NULL;
/* if node has left child, return left child */
if (wStartNode->left != NULL) return wStartNode->left;
/* if node has right child, return right child */
if (wStartNode->right != NULL) return wStartNode->right;
/* if node isLeaf
return right child of the closest ancestor whose right child is present and not yet processed*/
if (isLeaf(wStartNode)) {
TreeNode<ItemType> *cur = wStartNode;
TreeNode<ItemType> *y = wStartNode->parent;
while (y->right == NULL && y->parent!=NULL){
cur = y;
y = y->parent;
}
while (y != NULL && cur == y->right) {
cur = y;
y = y->parent;
}
return y->right;
}
}
bool CBinaryTree<ItemType>::isLeaf(TreeNode<ItemType> *wStartNode){
if (wStartNode->left == NULL && wStartNode->right == NULL) return true;
else return false;
};
Suppose you already have the basic binary tree procedures isempty(bt), root(bt), left(bt), and right(bt). Write a procedure isLeaf(bt) that returns true if the binary tree bt is a leaf node and false if it is not.
This is what I have:
proc isLeaf(bt)
if (isEmpty(bt))
error('The binary tree is empty.');
elseif (left(bt) < right(bt))
return true;
else return false;
Then write a procedure numLeaves(bt) that returns the number of leaves in the binary tree bt.
This is what I have:
proc numLeaves(bt)
if (isEmpty(bt))
error ('The binary tree is empty.');
elseif (count left(bt) + right(bt));
return (left(bt) + right(bt);
please could you correct?
You'll learn very little to nothing if you don't try to solve this yourself, but just for people coming here looking for an answer:
boolean isLeaf (BinaryTree bt) {
return !isempty(bt) && isempty(left(bt)) && isempty(right(bt));
}
int numLeaves (BinaryTree bt) {
if (isempty(bt))
return 0;
else if (isLeaf(bt))
return 1;
else
return numLeaves(left(bt)) + numLeaves(right(bt));
}
The main idea here is to use recursion:
The number of leaves a node has is the sum of the number of leaves its left child has, and the number of leaves its right child has.
As #jeffrey greenham said that we can use recursion
int countleaves(struct node* root){
if(root!=null)
{
countleaves(root->left);
if(root->left==NULL&&root->right==NULL)
{
count++;
}
countleaves(root->right);
}
}