Tree algo Flashcards

1
Q

applications of Trees:

A

To represent hierarchical data.
Binary Search Trees.
Binary heap
B and B+ Trees in DBMS
Spanning and Shortest path in computer networks
Parse Tree and Expression Tree in Compilers.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

implementation to represent a Binary Tree.

A

In Binary Tree every node has at most two children.
#include (bits/stdc++.h>
using namespace std;

struct Node  
{ 
  int key; 
  struct Node *left; 
  struct Node *right; 
  Node(int k){
      key=k;
      left=right=NULL;
  }
};

int main() {

	Node *root=new Node(10);
	root->left=new Node(20);
	root->right=new Node(30);
	root->left->left=new Node(40);
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Implementation of Inorder Traversal

A
#include (bits/stdc++.h>
using namespace std;
struct Node  
{ 
  int key; 
  struct Node *left; 
  struct Node *right; 
  Node(int k){
      key=k;
      left=right=NULL;
  }
};
void inorder(Node *root){
    if(root!=NULL){
        inorder(root->left);
        cout((root->key((" ";
        inorder(root->right);    
    }
}  

int main() {

	Node *root=new Node(10);
	root->left=new Node(20);
	root->right=new Node(30);
	root->right->left=new Node(40);
	root->right->right=new Node(50);
inorder(root); } 20 10 40 30 50
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Implementation of Preorder Traversal

A
#include (bits/stdc++.h>
using namespace std;
struct Node  
{ 
  int key; 
  struct Node *left; 
  struct Node *right; 
  Node(int k){
      key=k;
      left=right=NULL;
  }
};
void preorder(Node *root){
    if(root!=NULL){
        cout((root->key((" ";
        preorder(root->left);
        preorder(root->right);    
    }
}  

int main() {

	Node *root=new Node(10);
	root->left=new Node(20);
	root->right=new Node(30);
	root->right->left=new Node(40);
	root->right->right=new Node(50);
preorder(root); } 10 20 30 40 50
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Implementation of Postorder Traversal

A
#include (bits/stdc++.h>
using namespace std;
struct Node  
{ 
  int key; 
  struct Node *left; 
  struct Node *right; 
  Node(int k){
      key=k;
      left=right=NULL;
  }
};
void postorder(Node *root){
    if(root!=NULL){
        postorder(root->left);
        postorder(root->right);
        cout((root->key((" ";
    }
}  

int main() {

	Node *root=new Node(10);
	root->left=new Node(20);
	root->right=new Node(30);
	root->right->left=new Node(40);
	root->right->right=new Node(50);
postorder(root); } 20 40 50 30 10
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Implementation of function to calculate Height of Binary Tree

A

Height of Binary Tree is the number of nodes between the longest path from root to leaf node(including the root and leaf node).

#include (bits/stdc++.h>
using namespace std;
struct Node  
{ 
  int key; 
  struct Node *left; 
  struct Node *right; 
  Node(int k){
      key=k;
      left=right=NULL;
  }
};
int height(Node *root){
    if(root==NULL)
        return 0;
    else
        return (1+max(height(root->left),height(root->right)));
}  

int main() {

	Node *root=new Node(10);
	root->left=new Node(20);
	root->right=new Node(30);
	root->right->left=new Node(40);
	root->right->right=new Node(50);
cout((height(root); } output 3
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Print nodes at k distance in a tree

A

Nodes at distance k from the root are basically the nodes at (k+1)th level of the Binary Tree.

#include (bits/stdc++.h>
using namespace std;
struct Node  
{ 
  int key; 
  struct Node *left; 
  struct Node *right; 
  Node(int k){
      key=k;
      left=right=NULL;
  }
};
void printKDist(Node *root,int k){
    if(root==NULL)return;
    if(k==0){cout((root->key((" ";}
    else{
    printKDist(root->left,k-1);
    printKDist(root->right,k-1);
    }
}  

int main() {

	Node *root=new Node(10);
	root->left=new Node(20);
	root->right=new Node(30);
	root->left->left=new Node(40);
	root->left->right=new Node(50);
	root->right->right=new Node(70);
	root->right->right->right=new Node(80);
	int k=2;
printKDist(root,k); } 40 50 70
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Implement level order traversal for a binary tree

A

Level order traversal of a tree is breadth first traversal of binary tree

#include (bits/stdc++.h>
using namespace std;
struct Node  
{ 
  int key; 
  struct Node *left; 
  struct Node *right; 
  Node(int k){
      key=k;
      left=right=NULL;
  }
};
void printLevel(Node *root){
    if(root==NULL)return;
    queue(Node *>q;
    q.push(root);
    while(q.empty()==false){
        Node *curr=q.front();
        q.pop();
        cout((curr->key((" ";
        if(curr->left!=NULL)
            q.push(curr->left);
        if(curr->right!=NULL)
            q.push(curr->right);
    }
}  

int main() {

	Node *root=new Node(10);
	root->left=new Node(20);
	root->right=new Node(30);
	root->left->left=new Node(40);
	root->left->right=new Node(50);
	root->right->left=new Node(60);
	root->right->right=new Node(70);
printLevel(root); } 10 20 30 40 50 60 70
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Calculate size of binary tree

A

Size of Binary Tree is the total numbers of nodes present in that Tree.

#include (bits/stdc++.h>
using namespace std;
struct Node  
{ 
  int key; 
  struct Node *left; 
  struct Node *right; 
  Node(int k){
      key=k;
      left=right=NULL;
  }
};
int getSize(Node *root){
    if(root==NULL)
        return 0;
    else
        return 1+getSize(root->left)+getSize(root->right);
} 

int main() {

	Node *root=new Node(10);
	root->left=new Node(20);
	root->right=new Node(30);
	root->left->left=new Node(40);
	root->left->right=new Node(50);
	root->right->right=new Node(60);
cout((getSize(root); } 6
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Maximum node in a tree

A
#include (bits/stdc++.h>
using namespace std;
struct Node  
{ 
  int key; 
  struct Node *left; 
  struct Node *right; 
  Node(int k){
      key=k;
      left=right=NULL;
  }
};
int getMax(Node *root){
    if(root==NULL)
        return INT_MIN;
    else
        return max(root->key,max(getMax(root->left),getMax(root->right)));
} 

int main() {

	Node *root=new Node(20);
	root->left=new Node(80);
	root->right=new Node(30);
	root->right->left=new Node(40);
	root->right->right=new Node(50);
cout((getMax(root); } 80
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Iterative Inorder traversal

A

TC = theta(n)

SC - O(h)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Iterative Preorder Traversal (Simple)

A

A O(n) extra space and O(n) time solution

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Iterative Preorder Traversal (Space Optimized)

A

O(h) extra space and O(n) time solution

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Children Sum Parent
Given a Binary Tree. Check whether all of its nodes have the value equal to the sum of their child nodes.

Example 1:

Input:
     10
    /
  10 
Output: 1
Explanation: Here, every node is sum of
its left and right child.
Example 2:
Input:
       1
     /   \
    4     3
   /  \
  5    N
Output: 0
Explanation: Here, 1 is the root node
and 4, 3 are its child nodes. 4 + 3 =
7 which is not equal to the value of
root node. Hence, this tree does not
satisfy the given conditions.

Your Task:
You don’t need to read input or print anything. Your task is to complete the function isSumProperty() that takes the root Node of the Binary Tree as input and returns 1 if all the nodes in the tree satisfy the following properties. Else, it returns 0.
For every node, data value must be equal to the sum of data values in left and right children. Consider data value as 0 for NULL child. Also, leaves are considered to follow the property.

Expected Time Complexiy: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A

Algorithm:

For each node, if node is null or both child nodes are null, return true.
Else if left and right child are not null then store their value.
If sum of stored data of left and right child is equal to the current node data and recursively for the left and right subtree, parent data is equal to sum of child data then return true else return false.

int isSumProperty(struct Node *node) 
{
    int left_data = 0, right_data = 0;
    //if node is null or both child nodes are null, we return true.
    if (node == NULL ||(node->left == NULL && node->right == NULL))
        return 1;
else {
        //if left child is not null then we store its value.
        if (node->left != NULL)
            left_data = node->left->data;
        //if right child is not null then we store its value.
        if (node->right != NULL)
            right_data = node->right->data;
    //if sum of stored data of left and right child is equal to the current
    //node data and recursively for the left and right subtree, parent data 
    //is equal to sum of child data then we return true.
    if ((node->data == left_data + right_data) &&
        isSumProperty(node->left) &&
        isSumProperty(node->right))
        return 1;
        //else we return false.
        else
            return 0;
    }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Determine if Two Trees are Identical
Given two binary trees, the task is to find if both of them are identical or not.

Example 2:

Input:
     1          1
   /   \      /   \
  2     3    2     3
Output: Yes
Explanation: There are two trees both
having 3 nodes and 2 edges, both trees
are identical having the root as 1,
left child of 1 is 2 and right child
of 1 is 3.
Example 2:
Input:
    1       1
  /  \     /  \
 2    3   3    2
Output: No
Explanation: There are two trees both
having 3 nodes and 2 edges, but both
trees are not identical.

Your task:
Since this is a functional problem you don’t have to worry about input, you just have to complete the function isIdentical() that takes two roots as parameters and returns true or false. The printing is done by the driver code.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A

Two trees are identical when they have same data and arrangement of data is also same. To identify if two trees are identical, we need to traverse both trees simultaneously, and while traversing we need to compare data and children of the trees.

Algorithm:
1. If both nodes are empty then return 1.
2. Else If both nodes are non-empty
(a) Check data of the root nodes (tree1->data == tree2->data)
(b) Check left subtrees recursively.
(c) Check right subtrees recursively.
(d) If a,b and c are true then return 1.
3 Else return 0 (one is empty and other is not).

class Solution
{
    public:
    //Function to check if two trees are identical.
    bool isIdentical(Node* a, Node* b)
    {
        //if both nodes are null then we return true.
        if (a == NULL && b == NULL)
            return true;
    if (a != NULL && b != NULL)
    {
        //we check if data at both nodes and left and right subtree of
        //both the nodes are equal then we return true else return false.
        return
        (
            a->data == b->data &&
            isIdentical(a->left, b->left) &&
            isIdentical(a->right, b->right)
        );
    }
        //returning false if one of the nodes is null and other isn't.
        return false;
    }

};

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Level order traversal Line by Line

Given a Binary Tree, your task is to find its level order traversal.
For the below tree the output will be 1 $ 2 3 $ 4 5 6 7 $ 8 $.

          1
       /     \
     2        3
   /    \     /   \
  4     5   6    7
    \
     8

Example 1:

Input:
          1
        /
       4
     /   \
    4     2
Output:1 $ 4 $ 4 2 $

Example 2:

Input:
            10
          /    \
        20      30
     /     \
    40     60
Output: 10 $ 20 30 $ 40 60 $
Your Task:
This is a function problem. You don't need to read input. Just complete the function levelOrder() that takes nodes as parameter and returns level order traversal as a 2D list.

Note: The driver code prints the levels ‘$’ separated.
Expected Time Complexity: O(N).
Expected Auxiliary Space: O(N).

A

This question can be solved by simply using the concept of level order traversal but you just need to keep track of elements in a particular level and add them to final list.

vector(vector(int» levelOrder(struct Node* node)
{
//creating an empty queue for level order traversal.
queue(Node *> q;
q.push(node);

    vector(vector(int>> result;
    while(1)
    {
        int size = q.size();
        if(size==0)
            break;
        //creating a list to store the nodes at a particular level.
        vector(int> level;
        while(size>0)
        {
            //storing front element of queue in list and removing it from queue.
            Node * node = q.front();
            q.pop();
            level.push_back(node->data);
        //storing the left child of the parent node in queue.
        if(node->left)
            q.push(node->left);
            //storing the right child of the parent node in queue.
            if(node->right)
                q.push(node->right);
            size--;
        }
        //adding the level list in answer.
        result.push_back(level);
    }
    //returning the final list.
    return result;
}
17
Q

Maximum Width of Tree
Given a Binary Tree, find the maximum width of it. Maximum width is defined as the maximum number of nodes in any level.
For example, maximum width of following tree is 4 as there are 4 nodes at 3rd level.

          1
       /     \
     2        3
   /    \    /    \
  4    5   6    7
    \
      8

Example 1:

Input:
       1
     /    \
    2      3
Output: 2
Example 2:
Input:
        10
      /     \
    20      30
   /    \
  40    60
Output: 2
Your Task:
You don't have to read any input. Just complete the function getMaxWidth() that takes node as parameter and returns the maximum width. The printing is done by the driver code.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(N).

A
(Using Level Order Traversal) 
This method mainly involves two functions. One is to count nodes at a given level (getWidth), and other is to get the maximum width of the tree(getMaxWidth). getMaxWidth() makes use of getWidth() to get the width of all levels starting from root and compares them to get the maximum.
class Solution {
  public:
    // Function to get height of a tree.
    int height(Node* node) {
        // if node is null, we return 0.
        if (node == NULL) return 0;
        // else we call the function height recursively for left and right
        // subtrees of the parent node and store their maximum.
        else {
            int lHeight = height(node->left);
            int rHeight = height(node->right);
            return (lHeight > rHeight) ? (lHeight + 1) : (rHeight + 1);
        }
    }
  public:
    // Function to get width of a given level.
    int getWidth(Node* root, int level) {
    if (root == NULL) return 0;
        // if level is 1, we return 1.
        if (level == 1) return 1;
        // else if it is greater than one, we call the getWidth function
        // recursively for left and right subtrees of parent node and add them.
        else if (level > 1)
            return getWidth(root->left, level - 1) +
                   getWidth(root->right, level - 1);
    }
  public:
    // Function to get the maximum width of a binary tree.
    int getMaxWidth(Node* root) {
        int maxWidth = 0;
        int width;
        int h = height(root);
        int i;
        // getting width of each level and comparing the width
        // with maximum width so far.
        for (i = 1; i (= h; i++) {
            width = getWidth(root, i);
            if (width > maxWidth) maxWidth = width;
        }
        // returning the maximum width.
        return maxWidth;
    }
};
18
Q

Given a binary tree, find if it is height balanced or not.
A tree is height balanced if difference between heights of left and right subtrees is not more than one for all nodes of tree.

A height balanced tree
        1
     /     \
   10      39
  /
5
An unbalanced tree
        1
     /    
   10   
  /
5

Example 1:

Input:
      1
    /
   2
    \
     3 
Output: 0
Explanation: The max difference in height
of left subtree and right subtree is 2,
which is greater than 1. Hence unbalanced
Example 2:
Input:
       10
     /   \
    20   30 
  /   \
 40   60
Output: 1
Explanation: The max difference in height
of left subtree and right subtree is 1.
Hence balanced. 
Your Task:
You don't need to take input. Just complete the function isBalanced() that takes root node as parameter and returns true, if the tree is balanced else returns false.

Constraints:
1 <= Number of nodes <= 105
0 <= Data of a node <= 106

Expected time complexity: O(N)
Expected auxiliary space: O(h) , where h = height of tree

A

O(N) solution

int height(Node*root){
 if(root==NULL)return 0;
 return  1+max(height(root→left),height(root→right));
}
bool isBalanced(Node *root)
   {
       //  Your Code here
       bool flag=true;
if(root==NULL) return flag;
       queue(Node*> q;
       q.push(root);
       while(!q.empty()){
           Node*node=q.front();
           q.pop();
           if(abs(height(node->left)-height(node->right))>1)
           {
               flag=false;
               break;
           }
           if(node->left!=NULL)q.push(node->left);
           if(node->right!=NULL)q.push(node->right);
       }
       return flag;
   }
19
Q

Left View of Binary Tree
Given a Binary Tree, print Left view of it. Left view of a Binary Tree is set of nodes visible when tree is visited from Left side. The task is to complete the function leftView(), which accepts root of the tree as argument.

Left view of following tree is 1 2 4 8.

          1
       /     \
     2        3
   /     \    /    \
  4     5   6    7
   \
     8   

Example 1:

Input:
   1
 /  \
3    2
Output: 1 3

Example 2:

Input:

Output: 10 20 40
Your Task:
You just have to complete the function leftView() that prints the left view. The newline is automatically appended by the driver code.
Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A

Method-2 (Using Queue):

In this method, level order traversal based solution is discussed. If we observe carefully, we will see that our main task is to print the left most node of every level. So, we will do a level order traversal on the tree and print the leftmost node at every level. Below is the implementation of above approach:

// C++ program to print left view of
// Binary Tree
#include(bits/stdc++.h>
using namespace std;
// A Binary Tree Node
struct Node
{
	int data;
	struct Node *left, *right;
};
// Utility function to create a new tree node
Node* newNode(int data)
{
	Node *temp = new Node;
	temp->data = data;
	temp->left = temp->right = NULL;
	return temp;
}
// function to print left view of
// binary tree
void printLeftView(Node* root)
{
	if (!root)
		return;
queue(Node*> q;
q.push(root);
	while (!q.empty())
	{	
		// number of nodes at current level
		int n = q.size();
		// Traverse all nodes of current level
		for(int i = 1; i (= n; i++)
		{
			Node* temp = q.front();
			q.pop();
		// Print the left most element
		// at the level
		if (i == 1)
			cout((temp->data((" ";

		// Add left node to queue
		if (temp->left != NULL)
			q.push(temp->left);
			// Add right node to queue
			if (temp->right != NULL)
				q.push(temp->right);
		}
	}
}	
// Driver code
int main()
{
	// Let's construct the tree as
	// shown in example
	Node* root = newNode(10);
	root->left = newNode(2);
	root->right = newNode(3);
	root->left->left = newNode(7);
	root->left->right = newNode(8);
	root->right->right = newNode(15);
	root->right->left = newNode(12);
	root->right->right->left = newNode(14);
printLeftView(root); }
// This code is contributed by
// Manne SreeCharan
20
Q

Right View of Binary Tree

Given a Binary Tree, find Right view of it. Right view of a Binary Tree is set of nodes visible when tree is viewed from right side.

Right view of following tree is 1 3 7 8.

          1
       /     \
     2        3
   /   \      /    \
  4     5   6    7
    \
     8

Example 1:

Input:
       1
    /    \
   3      2
Output: 1 2
Example 2:
Input:
     10
    /   \
  20     30
 /   \
40  60 
Output: 10 30 60
Your Task:
Just complete the function rightView() that takes node as parameter and returns the right view as a list. 

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A
The problem can be solved using simple recursive traversal. We can keep track of level of a node by passing a parameter to all recursive calls. The idea is to keep track of maximum level also. And traverse the tree in a manner that right subtree is visited before left subtree. Whenever we see a node whose level is more than maximum level so far, we print the node because this is the last node in its level (Note that we traverse the right subtree before left subtree). Following is the implementation of this approach. 
class Solution
{
    public:
    //Function to get the right view of the binary tree.
    void rightViewUtil(vector(int> &vec,struct Node *root,int level,int *max_level)
    {
        //if root is null, we simply return.
        if (root==NULL)  return;
         //if this is the last node of its level then it is in the right view.
        if (*max_level ( level)
        {
            vec.push_back(root->data);
            *max_level = level;
        }
    //calling function recursively for right and left 
    //subtrees of current node.
    rightViewUtil(vec, root->right, level+1, max_level);
    rightViewUtil(vec, root->left, level+1, max_level);
}
    public:
    //Function to return list containing elements of right view of binary tree.
    vector(int> rightView(struct Node *root)
    {
        int max_level = 0;
        vector(int> vec;
        rightViewUtil(vec,root, 1, &max_level);
        //returning the list.
        return vec;
    }
};
Time Complexity: The function does a simple traversal of the tree, so the complexity is O(n).

Method 2: In this method, level order traversal based solution is discussed. If we observe carefully, we will see that our main task is to print the right most node of every level. So, we will do a level order traversal on the tree and print the last node at every level. Below is the implementation of above approach:

vector(int> rightView(Node *root)
    {
      vector(int>v;
       queue(Node*>q;
        q.push(root);
        while(!q.empty()){
            int n=q.size();
            for(int i=0;i(n;i++){
                Node *temp=q.front();
                q.pop();
                if(i==n-1){
                    v.push_back(temp->data);
                }
                if(temp->left!=NULL){
                    q.push(temp->left);
                }
                if(temp->right!=NULL){
                    q.push(temp->right);
                }
        }
    }
    return v;
}
21
Q

Lowest Common Ancestor in a Binary Tree

Given a Binary Tree with all unique values and two nodes value, n1 and n2. The task is to find the lowest common ancestor of the given two nodes. We may assume that either both n1 and n2 are present in the tree or none of them are present.

Example 1:

Input:
n1 = 2 , n2 = 3  
       1 
      / \ 
     2   3
Output: 1
Explanation:
LCA of 2 and 3 is 1.
Example 2:
Input:
n1 = 3 , n2 = 4
           5    
          /    
         2  
        / \  
       3   4
Output: 2
Explanation:
LCA of 3 and 4 is 2. 
Your Task:
You don't have to read, input, or print anything. Your task is to complete the function lca() that takes nodes, n1, and n2 as parameters and returns the LCA node as output. Otherwise, return a node with a value of -1 if both n1 and n2 are not present in the tree.

Expected Time Complexity:O(N).
Expected Auxiliary Space:O(Height of Tree).

A
Following is definition of LCA from Wikipedia: 
Let T be a rooted tree. The lowest common ancestor between two nodes n1 and n2 is defined as the lowest node in T that has both n1 and n2 as descendants (where we allow a node to be a descendant of itself).
The LCA of n1 and n2 in T is the shared ancestor of n1 and n2 that is located farthest from the root. Computation of lowest common ancestors may be useful, for instance, as part of a procedure for determining the distance between pairs of nodes in a tree: the distance from n1 to n2 can be computed as the distance from the root to n1, plus the distance from the root to n2, minus twice the distance from the root to their lowest common ancestor.
Method 1 (By Storing root to n1 and root to n2 paths): 

Following is simple O(n) algorithm to find lowest common ancestor of two numbers n1 and n2.

Find path from root to n1 and store it in a vector or array.
Find path from root to n2 and store it in another vector or array.
Traverse both paths till the values in arrays are same. Return the common element just before the mismatch.
Try another efficient approach using parent array.

bool findPath(Node *root, vector(int> &path, int k)
{
    // base case
    if (root == NULL) return false;
    // Store this node in path vector. The node will be removed if
    // not in path from root to k
    path.push_back(root->key);
    // See if the k is same as root's key
    if (root->key == k)
        return true;
// Check if k is found in left or right sub-tree
if ( (root->left && findPath(root->left, path, k)) ||
     (root->right && findPath(root->right, path, k)) )
    return true;
    // If not present in subtree rooted with root, remove root from
    // path[] and return false
    path.pop_back();
    return false;
}
// Returns LCA if node n1, n2 are present in the given binary tree,
// otherwise return -1
int findLCA(Node *root, int n1, int n2)
{
    // to store paths to n1 and n2 from the root
    vector(int> path1, path2;
    // Find paths from root to n1 and root to n1. If either n1 or n2
    // is not present, return -1
    if ( !findPath(root, path1, n1) || !findPath(root, path2, n2))
          return -1;
    /* Compare the paths to get the first different value */
    int i;
    for (i = 0; i ( path1.size() && i ( path2.size() ; i++)
        if (path1[i] != path2[i])
            break;
    return path1[i-1];
}

Method 2
The question is simply asking to find the subtree’s root which will contain both n1 and n2, right?! So we do the same,

Well, if there is no root, you gotta return null/root. if(root==nullptr) { return root; }

if your root data contains either n1 or n2, you return that root. WHY?? because it will be used in calculation of two different answer A.K.A. left and right side of tree.

Now save your Left answer of the left side of tree in a variable, this variable with either have a null or a valid node depending on recursive calls if it finds the required node, Do the same for the Right side make a variable and save the answer.

Now, we have two different variables namely left and right. Both contains answer either null or a valid node, now we check three conditions
If Left answer is not null and right answer is also not null, then the answer is the root itself, since left and right are subtrees of the root and if both are not null it clearly means the values n1 and n2 lies in right as well as left side, For example, Example test case 1 is the perfect example for this case
If left answer is not null but right answer is null, then it means both n1 and n2 lies on the left side of tree inside the subtree with root as left answer, return left answer. For example, Example test case 2 is the perfect example for this case

If right answer is not null but left answer is null, then it means both n1 and n2 lies on the right side of tree inside the subtree with root as right answer, return right answer.
Node* lca(Node* root ,int n1 ,int n2 )
{
if (root == NULL) return root;
if (root->data == n1 or root->data == n2) return root;

   Node* left = lca(root->left, n1, n2);
   Node* right = lca(root->right, n1, n2);
       if(left != NULL and right != NULL) return root;
       else if (left != NULL) return left;
       else return right;
    }
22
Q

Diameter of a Binary Tree
The diameter of a tree (sometimes called the width) is the number of nodes on the longest path between two end nodes. The diagram below shows two trees each with diameter nine, the leaves that form the ends of the longest path are shaded (note that there is more than one path in each tree of length nine, but no path longer than nine nodes).
Example 1:

Input:
       1
     /  \
    2    3
Output: 3
Example 2:
Input:
         10
        /   \
      20    30
    /   \ 
   40   60
Output: 4
Your Task:
You need to complete the function diameter() that takes root as parameter and returns the diameter.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A

The diameter of a tree T is the largest of the following quantities:

The diameter of T’s left subtree.
The diameter of T’s right subtree.
The longest path between leaves that goes through the root of T (this can be computed from the heights of the subtrees of T).

int ht(Node* root) {
        if(!root) return 0;
        if(!root->left and !root->right) return 1;
        int ld = 1 + ht(root->left);
        int rd = 1 + ht(root->right);
        return max(ld, rd);
    }
    int diameter(Node* root) {
        int res = 0;
        queue q;
        q.push(root);
        while(!q.empty()) {
            Node* temp = q.front();
            res = max(res, 1 + ht(temp->left) + ht(temp->right));
            q.pop();
            if(temp->left) q.push(temp->left);
            if(temp->right) q.push(temp->right);
        }
        return res;
    }

Optimized implementation: The above implementation can be optimized by calculating the height in the same recursion rather than calling a height() separately. Thanks to Amar for suggesting this optimized version. This optimization reduces time complexity to O(n).

// Recursive optimized C++ program to find the diameter of a
// Binary Tree
#include (bits/stdc++.h>
using namespace std;
// A binary tree node has data, pointer to left child
// and a pointer to right child
struct node {
	int data;
	struct node *left, *right;
};
// function to create a new node of tree and returns pointer
struct node* newNode(int data);
int diameterOpt(struct node* root, int* height)
{
	// lh --> Height of left subtree
	// rh --> Height of right subtree
	int lh = 0, rh = 0;
	// ldiameter --> diameter of left subtree
	// rdiameter --> Diameter of right subtree
	int ldiameter = 0, rdiameter = 0;
if (root == NULL) {
	*height = 0;
	return 0; // diameter is also 0
}
	// Get the heights of left and right subtrees in lh and
	// rh And store the returned values in ldiameter and
	// ldiameter
	ldiameter = diameterOpt(root->left, &lh);
	rdiameter = diameterOpt(root->right, &rh);
	// Height of current node is max of heights of left and
	// right subtrees plus 1
	*height = max(lh, rh) + 1;
	return max(lh + rh + 1, max(ldiameter, rdiameter));
}
// Helper function that allocates a new node with the
// given data and NULL left and right pointers.
struct node* newNode(int data)
{
	struct node* node
		= (struct node*)malloc(sizeof(struct node));
	node->data = data;
	node->left = NULL;
	node->right = NULL;
return (node); }
// Driver Code
int main()
{
	/* Constructed binary tree is
			1
			/ \
		2	 3
		/ \
	4	 5
	*/
	struct node* root = newNode(1);
	root->left = newNode(2);
	root->right = newNode(3);
	root->left->left = newNode(4);
	root->left->right = newNode(5);
	int height = 0;
	// Function Call
	cout (( "Diameter of the given binary tree is " (( diameterOpt(root, &height);
return 0; }

// This code is contributed by probinsah.

23
Q

Vertical Width of a Binary Tree
Given a Binary Tree of N nodes. Find the vertical width of the tree.

Example 1:

Input:
          1
       /    \
      2      3
     / \    / \
    4   5  6   7
            \   \
             8   9
Output: 6
Explanation: The width of a binary tree is
the number of vertical paths in that tree.

Example 2:

Input:
      1
    /  \
   2    3
Output: 3

Your Task:

You don’t have to read input or print anything. Your task is to complete the function verticalWidth() which takes root as the only parameter, and returns the vertical width of the binary tree.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A

Maintain 3 variables maximum and minimum, and curr.

Maximum and Minimum will store the max value of width of tree and min value of width of tree, over all recursion calls.

  1. Pass Maximum and Minimum through reference for updation.
  2. For call on left subree pass curr-1 and for call on right subree pass curr + 1

After all the calls have been made, return the sum of maximum and absolute value of minimum+1.

void lengthUtil(Node* root, int &maximum, int &minimum, int curr)
{
    //base case for recursion.
	if (root == NULL)return;
	//calling the lengthUtil function recursively for the left subtrees.
	lengthUtil(root->left, maximum, minimum, curr - 1);
	//updating maximum and minimum.
	if (minimum > curr)minimum = curr;
	if (maximum ( curr)maximum = curr;
	//calling the lengthUtil function recursively for the right subtrees.
	lengthUtil(root->right, maximum, minimum, curr + 1);
}
//Function to find the vertical width of a Binary Tree.
int verticalWidth(Node* root)
{
    if (!root) {
        return 0;
    }
	int maximum = 0, minimum = 0;
	lengthUtil(root, maximum, minimum, 0);
	//returning the result.
	return (abs(minimum) + maximum) + 1;
}
24
Q

Mirror Tree
Your Task:
Just complete the function mirror() that takes node as paramter and convert it into its mirror. The printing is done by the driver code only.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A
// Function to convert a binary tree into its mirror tree.
    void mirror(Node* node) {
        if (!node) return;
        swap(node->left, node->right);
        mirror(node->left);
        mirror(node->right);
    }
25
Q

Check if subtree is present in a tree

Given two binary trees with head reference as T and S having at most N nodes. The task is to check if S is present as subtree in T.
A subtree of a tree T1 is a tree T2 consisting of a node in T1 and all of its descendants in T1.

Example 1:

Input:
T:      1          S:   3
      /   \            /
     2     3          4
   /  \    /
  N    N  4
Output: 1 
Explanation: S is present in T

Example 2:

Input:
T:      26         S:   26
       /   \           /  \
     10     N        10    N
   /    \           /  \
   20    30        20  30
  /  \            /  \
 40   60         40  60
Output: 1 
Explanation: 
S and T are both same. Hence, 
it can be said that S is a subtree 
of T.
Your Task:
You don't need to read input or print anything. Your task is to complete the function isSubtree() that takes root node of S and T as parameters and returns 1 if S is a subtree of T else 0.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(N).

A

Algorithm:

Find inorder and preorder traversals of T, store them in two lists.
Find inorder and preorder traversals of S, store them in two lists.
If inorder and preorder lists of T occurs in inorder and preorder lists of S then return true else false.

class Solution {
    vector(Node*> nodes;
public:
    bool isSubTree(Node* S, Node* T) {
        if (!S && !T) return true;
        if (!S || !T) return false;
        getDepth(S, getDepth(T, -1));
        for (Node* n: nodes)
            if (identical(n, T))
                return true;
        return false;
    }
    int getDepth(Node* r, int d) {
        if (!r)
            return -1;
        int depth = max(getDepth(r->left, d), getDepth(r->right, d)) + 1;
        // Check if depth equals required value
        // Require depth is -1 for tree t (only return the depth, no push)
        if (depth == d)
            nodes.push_back(r);
        return depth;
    }
    bool identical(Node* a, Node* b) {
        if (!a && !b) return true;
        if (!a || !b || a->data != b->data) return false;
        return identical(a->left, b->left) && identical(a->right, b->right);
    }
};

another approach
One simple approach is to check if the node data is same and then check for subtree from that node.
Do this recursively for left and right subtree.

class Solution
{
 public:
   bool isSame(Node *a,Node*b)  // to check if both the subtrees are same
   {
    if(a==NULL && b==NULL) //base case
    return true;
    if(a==NULL||b==NULL) // base case
    return false;
    if(a->data!=b->data) // base case
    return false;
    return isSame(a->left,b->left) && isSame(a->right,b->right); // recurcive call to check for left and right subtrees
   }
   bool isSubTree(Node* T, Node* S) 
   {
       // Your code here
       if(T==NULL && S==NULL) // base case
       return true;
       if(T==NULL)  // base case
       return false;
       if(T->data==S->data&&isSame(T,S))  // if any node's data is found same check for same subtree
       return true;
       return isSubTree(T->left,S)||isSubTree(T->right,S);  // recursively check for left and right subtree

}
};

26
Q

Given a Binary Tree (Bt), convert it to a Doubly Linked List(DLL). The left and right pointers in nodes are to be used as previous and next pointers respectively in converted DLL. The order of nodes in DLL must be the same as in Inorder for the given Binary Tree. The first node of Inorder traversal (leftmost node in BT) must be the head node of the DLL.

Example 1:

Input:
      1
    /  \
   3    2
Output:
3 1 2 
2 1 3 
Explanation: DLL would be 3<=>1<=>2
Example 2:
Input:
       10
      /   \
     20   30
   /   \
  40   60
Output:
40 20 60 10 30 
30 10 60 20 40
Explanation:  DLL would be 
40<=>20<=>60<=>10<=>30.
Your Task:
You don't have to take input. Complete the function bToDLL() that takes root node of the tree as a parameter and returns the head of DLL . The driver code prints the DLL both ways.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(H).
Note: H is the height of the tree and this space is used implicitly for the recursion stack.

A

Algorithm:

Traverse the tree in inorder fashion.
While visiting each node, keep track of DLL’s head and tail pointers, insert each visited node to the end of DLL using tail pointer.
Return head of the list.
Below is the implementation of the above approach:

// A C++ program for in-place
// conversion of Binary Tree to DLL
#include (bits/stdc++.h>
using namespace std;
/* A binary tree node has data,
and left and right pointers */
class node {
public:
	int data;
	node* left;
	node* right;
};
/* This is the core function to convert
Tree to list.*/
void bintree2listUtil(node* root, node** head, node** tail)
{
	if (root == NULL)
		return;
bintree2listUtil(root->left, head, tail);

if (*head == NULL) {
	*head = root;
}

root->left = *tail;

if (*tail != NULL) {
	(*tail)->right = root;
}

*tail = root;

bintree2listUtil(root->right, head, tail); }
// The main function that first calls
// bintree2listUtil()
node* bintree2list(node* root)
{
	// Base case
	if (root == NULL)
		return root;
node* head = NULL;
node* tail = NULL;

bintree2listUtil(root, &head, &tail);

return head; }
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
node* newNode(int data)
{
	node* new_node = new node();
	new_node->data = data;
	new_node->left = new_node->right = NULL;
	return (new_node);
}
/* Function to print nodes in a given doubly linked list */
void printList(node* node)
{
	while (node != NULL) {
		cout (( node->data (( " ";
		node = node->right;
	}
}
/* Driver code*/
int main()
{
	// Let us create the tree shown in above diagram
	node* root = newNode(10);
	root->left = newNode(12);
	root->right = newNode(15);
	root->left->left = newNode(25);
	root->left->right = newNode(30);
	root->right->left = newNode(36);
	// Convert to DLL
	node* head = bintree2list(root);
	// Print the converted list
	printList(head);
return 0; }
27
Q

Convert a Binary Tree to a Circular Doubly Link List
Given a Binary Tree, convert it to a Circular Doubly Linked List (In-Place).

The left and right pointers in nodes are to be used as previous and next pointers respectively in converted Circular Linked List.
The order of nodes in the List must be the same as in Inorder for the given Binary Tree.
The first node of Inorder traversal must be the head node of the Circular List.
Example:

A

The idea can be described using the below steps.
1) Write a general-purpose function that concatenates two given circular doubly lists (This function is explained below).
2) Now traverse the given tree
….a) Recursively convert left subtree to a circular DLL. Let the converted list be leftList.
….a) Recursively convert right subtree to a circular DLL. Let the converted list be rightList.
….c) Make a circular linked list of root of the tree, make left and right of root to point to itself.
….d) Concatenate leftList with the list of the single root node.
….e) Concatenate the list produced in the step above (d) with rightList.
Note that the above code traverses the tree in Postorder fashion. We can traverse in an inorder fashion also. We can first concatenate left subtree and root, then recur for the right subtree and concatenate the result with left-root concatenation.

How to Concatenate two circular DLLs?

Get the last node of the left list. Retrieving the last node is an O(1) operation since the prev pointer of the head points to the last node of the list.
Connect it with the first node of the right list
Get the last node of the second list
Connect it with the head of the list.
Below are implementations of the above idea.

// C++ Program to convert a Binary Tree
// to a Circular Doubly Linked List
#include(iostream>
using namespace std;
// To represents a node of a Binary Tree
struct Node
{
	struct Node *left, *right;
	int data;
};
// A function that appends rightList at the end
// of leftList.
Node *concatenate(Node *leftList, Node *rightList)
{
	// If either of the list is empty
	// then return the other list
	if (leftList == NULL)
		return rightList;
	if (rightList == NULL)
		return leftList;
	// Store the last Node of left List
	Node *leftLast = leftList->left;
	// Store the last Node of right List
	Node *rightLast = rightList->left;
	// Connect the last node of Left List
	// with the first Node of the right List
	leftLast->right = rightList;
	rightList->left = leftLast;
	// Left of first node points to
	// the last node in the list
	leftList->left = rightLast;
	// Right of last node refers to the first
	// node of the List
	rightLast->right = leftList;
return leftList; }

// Function converts a tree to a circular Linked List
// and then returns the head of the Linked List
Node *bTreeToCList(Node *root)
{
if (root == NULL)
return NULL;

	// Recursively convert left and right subtrees
	Node *left = bTreeToCList(root->left);
	Node *right = bTreeToCList(root->right);
	// Make a circular linked list of single node
	// (or root). To do so, make the right and
	// left pointers of this node point to itself
	root->left = root->right = root;
	// Step 1 (concatenate the left list with the list
	//		 with single node, i.e., current node)
	// Step 2 (concatenate the returned list with the
	//		 right List)
	return concatenate(concatenate(left, root), right);
}
// Display Circular Link List
void displayCList(Node *head)
{
	cout (( "Circular Linked List is :\n";
	Node *itr = head;
	do
	{
		cout (( itr->data ((" ";
		itr = itr->right;
	} while (head!=itr);
	cout (( "\n";
}
// Create a new Node and return its address
Node *newNode(int data)
{
	Node *temp = new Node();
	temp->data = data;
	temp->left = temp->right = NULL;
	return temp;
}
// Driver Program to test above function
int main()
{
	Node *root = newNode(10);
	root->left = newNode(12);
	root->right = newNode(15);
	root->left->left = newNode(25);
	root->left->right = newNode(30);
	root->right->left = newNode(36);
Node *head = bTreeToCList(root);
displayCList(head);

return 0; } Output:  

Circular Linked List is :
25 12 30 10 36 15

28
Q

Connect Nodes at Same Level
Given a binary tree, connect the nodes that are at same level. You’ll be given an addition nextRight pointer for the same.

Initially, all the nextRight pointers point to garbage values. Your function should set these pointers to point next right for each node.
10 10 ——> NULL
/ \ / \
3 5 => 3 ——> 5 ——–> NULL
/ \ \ / \ \
4 1 2 4 –> 1 —–> 2 ——-> NULL

Example 1:

Input:
     3
   /  \
  1    2
Output:
3 1 2
1 3 2
Explanation:The connected tree is
        3 ------> NULL
     /    \
    1-----> 2 ------ NULL
Example 2:
Input:
      10
    /   \
   20   30
  /  \
 40  60
Output:
10 20 30 40 60
40 20 60 10 30
Explanation:The connected tree is
         10 ----------> NULL
       /     \
     20 ------> 30 -------> NULL
  /    \
 40 ----> 60 ----------> NULL
Your Task:
You don't have to take input. Complete the function connect() that takes root as parameter and connects the nodes at same level. The printing is done by the driver code. First line of the output will be level order traversal and second line will be inorder travsersal

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(N).

A

Traverse the nextRight node before the left and right children (root, nextRight, left), then we can make sure that all nodes at level i have the nextRight set, before the level i+1 nodes.

In this method, we make sure that all nodes at the 4’s level (level 2) have nextRight set, before we try to set the nextRight of 9. So when we set the nextRight of 9, we search for a nonleaf node on right side of node 4 (getNextRight() does this for us).

        1            -------------- Level 0
      /    \
    2        3       -------------- Level 1
   / \      /  \
  4   5    6    7    -------------- Level 2
 / \           / \
8   9        10   11 -------------- Level 3
class Solution
{
    public:
    //Function to connect nodes at same level.
    void connect(Node *root)
    {
        //creating queue for level order traversal of tree.
        queue (Node*> q;
        q.push(root);
        //prev holds the value of previous node on the particular level.
        Node* prev=NULL;
        //end will hold value of last node of a level
        //and nextend will store the same for the next level.
        Node* end = root, *nextend;
        while(!q.empty())
        {
            //storing the front element of queue in temp and popping it.
            Node* temp = q.front();
            q.pop();
            //storing all available nodes in queue and updating nextend.
            if(temp->left) 
            { 
                q.push(temp->left);
                nextend = temp->left;
            }
            if(temp->right)
            { 
                q.push(temp->right);
                nextend = temp->right;
            }
            //setting nextRight of previous node of that level.
            if(prev) 
            prev->nextRight = temp;
            //if we reach the end of a level, we set nextRight of the 
            //current node and prev to NULL.
            if(temp == end)
            {
                temp->nextRight = NULL;
                prev = NULL;
                //we also set the value of end for next level.
                end = nextend;
            }
            //else we set prev to current node temp. 
            else 
            prev = temp;
        }
    }

};

29
Q

Construct Binary Tree from Parent Array

Given an array that represents a tree in such a way that array indexes are values in tree nodes and array values give the parent node of that particular index (or node). The value of the root node index would always be -1 as there is no parent for root. Construct the standard linked representation of given Binary Tree from this given representation.
Examples:

Input: parent[] = {1, 5, 5, 2, 2, -1, 3}
Output: root of below tree
          5
        /  \
       1    2
      /    / \
     0    3   4
         /
        6 
Explanation: 
Index of -1 is 5.  So 5 is root.  
5 is present at indexes 1 and 2.  So 1 and 2 are
children of 5.  
1 is present at index 0, so 0 is child of 1.
2 is present at indexes 3 and 4.  So 3 and 4 are
children of 2.  
3 is present at index 6, so 6 is child of 3.
Input: parent[] = {-1, 0, 0, 1, 1, 3, 5};
Output: root of below tree
         0
       /   \
      1     2
     / \
    3   4
   /
  5 
 /
6

Expected Time Complexity: O(N)
Expected Auxiliary Space: O(N)

A

Approach :
Step 1:
The simple method to solve this problem is we just creat first an array of Node having value at nodes from 0 to N-1 because we know from the question is that the indexes of parent array is represent values of Node and the value of parent array is represent the parent Node having this value of the Node having value equal to the index.

step 2:
Now we have an array of Nodes of tree. so we will traverse the parent array and will check if parent[i] = -1 then mark arr[i] as root of tree. if arr[parent[i]]->left or arr[parent[i]]->right is NULL then make arr[parent[i]]->left or arr[parent[i]]->right = arr[i] accordingly .

step 3: Now return the root of tree.

class Solution{
  public:
    //Function to construct binary tree from parent array.
    Node *createTree(int parent[], int N)
    {
        Node *arr[N];
        Node *root;
        for(int i=0;i(N;i++)
        {
            arr[i] = new Node(i);
        }
       for(int i=0;i(N;i++)
       {
           if(parent[i]==-1)
           {
              root = arr[i];
           }
           else
           {
               if(arr[parent[i]]->left==NULL)
                arr[parent[i]]->left = arr[i];
               else if(arr[parent[i]]->right==NULL)
                arr[parent[i]]->right = arr[i];
           }
       }
      return root;  
    }
};
30
Q

Given a binary tree, check if the tree can be folded or not. A tree can be folded if left and right subtrees of the tree are structure wise same. An empty tree is considered as foldable.
Consider the below trees:
(a) and (b) can be folded.
(c) and (d) cannot be folded.

(a)
       10
     /    \
    7      15
     \    /
      9  11
(b)
        10
       /  \
      7    15
     /      \
    9       11
(c)
        10
       /  \
      7   15
     /    /
    5   11
(d)
         10
       /   \
      7     15
    /  \    /
   9   10  12

Example 1:

Input:
     10
    /    \
   7     15
 /  \   /  \
N   9  11   N
Output:Yes
Example 2:
Input:
      10
    /    \
   7     15
 /  \   /  \
5   N  11   N
Output: No

Your Task:
The task is to complete the function isFoldable() that takes root of the tree as input and returns true or false depending upon whether the tree is foldable or not.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A

Method- (Check if Left and Right subtrees are Mirror)

There are mainly two functions:
1. First function IsFoldable(root) which checks if tree can be folded or not.

If tree is empty then return true
Else check if left and right subtrees are structure wise mirrors of each other. Use utility function IsFoldableUtil(root->left,root->right) for this.
2. Second function IsFoldableUtil(n1, n2) which checks if two trees with roots n1 and n2 are mirror of each other.

If both trees are empty then return true.
If one of them is empty and other is not then return false.
Return true if following conditions are met
a) n1->left is mirror of n2->right
b) n1->right is mirror of n2->left

//Function that checks if trees with roots n1 and n2 are mirror of each other.
bool IsFoldableUtil(Node *n1, Node *n2) 
{
    //if both left and right subtrees are NULL then we return true.
    if (n1 == NULL && n2 == NULL) 
    {
        return true;
    }
    //if one of the trees is NULL and other is not then we return false.
    if (n1 == NULL || n2 == NULL) {
        return false;
    }
    //else we check recursively if left and right subtrees are 
    //mirrors of their counterparts.
    return IsFoldableUtil(n1->left,n2->right)&&IsFoldableUtil(n1->right,n2->left);
}
//Function to check whether a binary tree is foldable or not.
bool IsFoldable(Node *root) 
{
    if (root == NULL) 
    {
        return true;
    }
    return IsFoldableUtil(root->left, root->right);
}
31
Q

Maximum path sum from any node
Given a binary tree, the task is to find the maximum path sum. The path may start and end at any node in the tree.

Example 1:

Input:
     10
    /  \
   2   -25
  / \  /  \
 20 1  3  4
Output: 32
Explanation: Path in the given tree goes
like 10 , 2 , 20 which gives the max
sum as 32.
Example 2:
Input:
     10
   /    \
  2      5
          \
          -2
Output: 17
Explanation: Path in the given tree goes
like 2 , 10 , 5 which gives the max sum
as 17.
Your Task:
You don't need to take input or print anything. Your task is to complete the function findMaxSum() that takes root as input and returns max sum between any two nodes in the given Binary Tree.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A

For each node there can be four ways that the max path goes through the node:

  1. Node only
  2. Max path through Left Child + Node
  3. Max path through Right Child + Node
  4. Max path through Left Child + Node + Max path through Right Child
The idea is to keep trace of four paths and pick up the max one in the end. An important thing to note is, root of every subtree needs to return maximum path sum such that at most one child of root is involved. This is needed for parent function call.
class Solution {
  public:
    //Function to calculate maximum path sum.
    int findMaxUtil(Node *root, int &res)
    {
        //base case for recursion.
        if (root == NULL)
            return 0;
        //l and r store maximum path sum going recursively through left and
        //right subtrees of root(current node) respectively.
        int l = findMaxUtil(root->left, res);
        int r = findMaxUtil(root->right, res);
        //max path sum for parent call of root. This path must
        //include at-most one child of root.
        int max_single = max(max(l, r) + root->data, root->data);
        //max_top represents the sum when the node under consideration is the root
        //of the max sum path and no ancestors of root are there in max sum path. 
        int max_top = max(max_single, l + r + root->data);
        //storing the maximum result.
        res = max(res, max_top); 
    return max_single;
}
    //Function to return maximum path sum from any node in a tree.
    int findMaxSum(Node *root) 
    {
        int res = INT_MIN;
        findMaxUtil(root, res);
        //returning the result.
        return res;
    }
};
32
Q

Maximum difference between node and its ancestor in Binary Tree
Given a binary tree, we need to find maximum value we can get by subtracting value of node B from value of node A, where A and B are two nodes of the binary tree and A is an ancestor of B. Expected time complexity is O(n).

For example, consider below binary tree

We can have various ancestor-node difference, some of which are given below :
8 – 3 = 5
3 – 7 = -4
8 – 1 = 7
10 – 13 = -3
. . . .
But among all those differences maximum value is 7 obtained by subtracting 1 from 8, which we need to return as result.

A

As we are given a binary tree, there is no relationship between node values so we need to traverse whole binary tree to get max difference and we can obtain the result in one traversal only by following below steps:
If we are at leaf node then just return its value because it can’t be ancestor of any node. Then at each internal node we will try to get minimum value from left subtree and right subtree and calculate the difference between node value and this minimum value and according to that we will update the result.
As we are calculating minimum value while returning in recurrence, we will check all optimal possibilities (checking node value with minimum subtree value only) of differences and hence calculate the result in one traversal only.

//Function to find the maximum difference.
int maxDiffUtil(Node *t,int *res)
{
    //returning Maximum int value if node is null.
    if (t == NULL) 
        return INT_MAX; 
    //if there are no child nodes then we just return data at current node.
    if (t->left == NULL && t->right == NULL) 
        return t->data; 
    //recursively calling for left and right subtrees and 
    //choosing their minimum.
    int val = min(maxDiffUtil(t->left, res), 
                  maxDiffUtil(t->right, res)); 
    //updating res if (node value - min value from subtrees) is bigger than res.
    *res = max(*res, t->data - val); 
    //returning minimum value got so far.
    return min(val, t->data);
}
//Function to return the maximum difference between any node and its ancestor.
int maxDiff(Node *root)
{
33
Q

Given a binary tree and an integer X. Your task is to complete the function countSubtreesWithSumX() that returns the count of the number of subtress having total node’s data sum equal to the value X.
Example: For the tree given below:

              5
            /    \
        -10     3
        /    \    /  \
      9     8  -4 7

Subtree with sum 7:
-10
/ \
9 8

and one node 7.

Example 1:

Input:
       5
    /    \
  -10     3
 /   \   /  \
 9   8 -4    7
X = 7
Output: 2
Explanation: Subtrees with sum 7 are
[9, 8, -10] and [7] (refer the example
in the problem description).
Example 2:
Input:
    1
  /  \
 2    3
X = 5
Output: 0
Explanation: No subtree has sum equal
to 5.
Your Task:
You don't need to read input or print anything. Your task is to complete the function countSubtreesWithSumX() which takes the root node and an integer X as inputs and returns the number of subtrees of the given Binary Tree having sum exactly equal to X.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A

Approach:

There are mainly two functions:
1. First function countSubtreesWithSumX(root, count, x) which counts number of subtrees having sum equal to given sum.

If root is null then return 0.
Find the sum of left and right subtrees using the other function.
If sum of left and right subtrees and data at current node is equal to given sum increment the counter.
Return the count.
2. Second function countSubtreesWithSumXUtil(root, x) which find the sum of nodes in given subtree.

If root is null then return 0.
Find the sum of left and right subtrees recursively.
If sum of left and right subtrees and data at current node is equal to given sum increment the counter.
Return the sum.

//Function to find the sum of nodes in given subtree.
int countSubtreesWithSumXUtil(Node* root, int& count, int x)
{
if (!root)
return 0;
	//finding sum of nodes in the left and right subtrees recursively.
	int ls = countSubtreesWithSumXUtil(root->left, count, x);
	int rs = countSubtreesWithSumXUtil(root->right, count, x);
	int sum = ls + rs + root->data;
//if sum of ls, rs and current node data is equal to x,
//we increment the counter.
if (sum == x)
count++;
	//returning the sum.
	return sum;
}
//Function to count number of subtrees having sum equal to given sum.
int countSubtreesWithSumX(Node* root, int x)
{ 
	if (!root)
	return 0;
	int count = 0;
	//finding sum of nodes in the left subtrees.
	int ls = countSubtreesWithSumXUtil(root->left, count, x);
	//finding sum of nodes in the right subtrees. 
	int rs = countSubtreesWithSumXUtil(root->right, count, x);
//if sum of ls,rs and current node data is equal to x,
//we increment the counter.
if ((ls + rs + root->data) == x)
count++;
	//returning the count.
	return count;
}
34
Q

Serialize and Deserialize a Binary Tree

Serialization is to store a tree in an array so that it can be later restored and Deserialization is reading tree back from the array. Now your task is to complete the function serialize which stores the tree into an array A[ ] and deSerialize which deserializes the array to the tree and returns it.
Note: The structure of the tree must be maintained. Multiple nodes can have the same data.

Example 1:

Input:
      1
    /   \
   2     3
Output: 2 1 3
Example 2:
Input:
         10
       /    \
      20    30
    /   \
   40  60
Output: 40 20 60 10 30
Your Task:
The task is to complete two function serialize which takes the root node of the tree as input and stores the tree into an array and deSerialize which deserializes the array to the original tree and returns the root of it.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(N).

A

Use DFS for serializing and deserializing.
Make function call to child nodes once we are done with the parent node

For serializing the tree into a list.

If node is null, store -1 in list and return
Store the data at current node in list.
Call function recursively for left and right subtrees.
Return the list.
For deserializing the list into a tree.

If there are no more elements in list, return null.
Create new node for storing current element.
Call function recursively for left and right subtrees.
Return the tree.

class Solution
{
    public:
    //Function to store the nodes of tree in the list.
    void serializeUtil(Node*root,vector(int>&a)
    {
        //base case if node is null.
        if (root == NULL) {
            a.push_back(-1);
            return;
        }
        //storing the data at node in list.
        a.push_back(root->data);
    //calling function recursively for left and right subtrees.
    serializeUtil(root->left, a);
    serializeUtil(root->right, a);
}
    //Function to serialize a tree and return a list containing nodes of tree.
    vector(int> serialize(Node *root)
    {
        vector(int> serialized;
        serializeUtil(root,serialized);
        //returning the list.
        return serialized;
    }
    //Function to construct the tree.
    Node *kewl(vector(int> &a, int *index) 
    {
        //base case if there are no more elements in list.
        if (*index == a.size() or a[*index] == -1) {
            *index += 1;
            return NULL;
        }
        //creating new node for storing current element.
        Node *root = new Node(a[*index]);
        *index += 1;
        //calling function recursively for left and right subtrees. 
        root->left = kewl(a, index);
        root->right = kewl(a, index);
        return root;
    }
    //Function to deserialize a list and construct the tree.
    Node *deSerialize(vector(int> &a) 
    {
        int index = 0;
        //returning the tree.
        return kewl(a, &index);
    }
};
35
Q

Node at distance
Given a Binary Tree and a positive integer k. The task is to count all distinct nodes that are distance k from a leaf node. A node is at k distance from a leaf if it is present k levels above the leaf and also, is a direct ancestor of this leaf node. If k is more than the height of Binary Tree, then nothing should be counted.

Example 1:

Input:
        1
      /   \
     2     3
   /  \   /  \
  4   5  6    7
          \ 
          8
K = 2
Output: 2
Explanation: There are only two unique
nodes that are at a distance of 2 units
from the leaf node. (node 3 for leaf
with value 8 and node 1 for leaves with
values 4, 5 and 7)
Note that node 2
isn't considered for leaf with value
8 because it isn't a direct ancestor
of node 8.
Example 2:
Input:
          1
         /
        3
       /
      5
    /  \
   7    8
         \
          9
K = 4
Output: 1
Explanation: Only one node is there
which is at a distance of 4 units
from the leaf node.(node 1 for leaf
with value 9) 
Your Task:
You don't have to read input or print anything. Complete the function printKDistantfromLeaf() that takes root node and k as inputs and returns the number of nodes that are at distance k from a leaf node. Any such node should be counted only once. For example, if a node is at a distance k from 2 or more leaf nodes, then it would add only 1 to our count.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).

A
void serAndPush(Node*root,vector(Node*>v,int k,set(Node*>&s){
   if(root==NULL) return;
   v.push_back(root);
   serAndPush(root->left,v,k,s);
   serAndPush(root->right,v,k,s);
   if(root->left==NULL && root->right==NULL){
       if(k>=v.size()) return;
       int t=0;
       for(int i=v.size()-1;i>=0;i--){
           if(t==k){
               s.insert(v[i]);
               return;
           }
           t++;
       }
   }
}
int printKDistantfromLeaf(Node* root, int k)
{
	set(Node*>s;
vector(Node*>v;
serAndPush(root,v,k,s);
return s.size();
}
36
Q

Given a Binary Tree. Find the Zig-Zag Level Order Traversal of the Binary Tree.

Example 1:

Input:
        3
      /   \
     2     1
Output:
3 1 2
Example 2:
Input:
           7
        /     \
       9       7
     /  \     /   
    8    8   6     
   /  \
  10   9 
Output:
7 7 9 8 8 6 9 10 

Your Task:
You don’t need to read input or print anything. Your task is to complete the function zigZagTraversal() which takes the root node of the Binary Tree as its input and returns a list containing the node values as they appear in the Zig-Zag Level-Order Traversal of the Tree.

Expected Time Complexity: O(N).
Expected Auxiliary Space: O(N).

A

This problem can be solved using two stacks. Assume the two stacks are current: currentlevel and nextlevel. We would also need a variable to keep track of the current level order (whether it is left to right or right to left). We pop from the currentlevel stack and print the nodes value. Whenever the current level order is from left to right, push the nodes left child, then its right child to the stack nextlevel. Since a stack is a LIFO(Last-In-First-out) structure, next time when nodes are popped off nextlevel, it will be in the reverse order. On the other hand, when the current level order is from right to left, we would push the nodes right child first, then its left child. Finally, do-not forget to swap those two stacks at the end of each level (i.e., when current level is empty)

class Solution{
    public:
//Function to store the zig zag order traversal of tree in a list.
vector (int> zigZagTraversal(Node* root)
{
    vector (int> res;
    //if root is null, we return the list.
	if (!root)return res;
	//declaring two stacks to store the current and new level.
	stack(struct Node*> currentlevel;
	stack(struct Node*> nextlevel;
	//pushing the root in currentlevel stack.
	currentlevel.push(root);
	bool lefttoright = true;
	while (!currentlevel.empty())
	{
	    //storing the top element of currentlevel stack in temp and popping it.
		Node* temp = currentlevel.top();
		currentlevel.pop();
	//if temp is not null, we store the data at temp in list.
	if (temp) 
	{
		res.push_back (temp->data);
			//if lefttoright is true then it stores nodes from left to right 
			//else from right to left in nextlevel stack.
			if (lefttoright)
			{
				if (temp->left)
					nextlevel.push(temp->left);
				if (temp->right)
					nextlevel.push(temp->right);
			}
			else 
			{
				if (temp->right)
					nextlevel.push(temp->right);
				if (temp->left)
					nextlevel.push(temp->left);
			}
		}
		//if currentlevel stack is empty lefttoright is flipped to change 
		//the order of storing the nodes and both stacks are swapped.
		if (currentlevel.empty()) 
		{
			lefttoright = !lefttoright;
			swap(currentlevel, nextlevel);
		}
	}
	//returning the list.
	return res;
}
};
37
Q

Given a binary tree with a value associated with each node, we need to choose a subset of these nodes such that sum of chosen nodes is maximum under a constraint that no two chosen node in subset should be directly connected that is, if we have taken a node in our sum then we can’t take its any children or parents in consideration and vice versa.

Example 1:

Input:
     11
    /  \
   1    2
Output: 11
Explanation: The maximum sum is sum of
node 11.
Example 2:
Input:
        1
      /   \
     2     3
    /     /  \
   4     5    6
Output: 16
Explanation: The maximum sum is sum of
nodes 1 4 5 6 , i.e 16. These nodes are
non adjacent.
Your Task:
You don't need to read input or print anything. You just have to complete function getMaxSum() which accepts root node of the tree as parameter and returns the maximum sum as described.

Expected Time Complexity: O(Number of nodes in the tree).
Expected Auxiliary Space: O(Height of the Tree).

A

Return a pair for each node in the binary tree such that the first of the pair indicates maximum sum when the data of a node is included and the second indicates maximum sum when the data of a particular node is not included.

class Solution{
  public:
    //Function which returns a pair such that first of the pair indicates maximum 
    //sum when data of a node is included and the second when it is not included.
    pair(int, int> maxSumHelper(Node *root) 
    { 
        //if root is null, we return two zeroes in pair.
    	if (root==NULL) 
    	{ 
    		pair(int, int> sum(0, 0); 
    		return sum; 
    	} 
    	//calling function recursively for left and right subtrees.
    	pair(int, int> sum1 = maxSumHelper(root->left); 
    	pair(int, int> sum2 = maxSumHelper(root->right); 
    	pair(int, int> sum; 
    	//current node is included (Left and right children are not included). 
    	sum.first = sum1.second + sum2.second + root->data; 
    	//current node is excluded (Either left or right child is included).
    	sum.second = max(sum1.first, sum1.second) + 
    				max(sum2.first, sum2.second); 
	return sum; 
} 
    //Function to return the maximum sum of non-adjacent nodes.
    int getMaxSum(Node *root) 
    { 
    	pair(int, int> res = maxSumHelper(root);
    	//returning the maximum between the elements in pair(res).
    	return max(res.first, res.second); 
    } 
};