Given the root of a binary tree and a node, return all cousins (not siblings) of the given node in the order of their appearance. If no cousins exist, return [-1].
Examples:
Input: root[] = [1, 2, 3, 4, 5, 6, 7], node = 5
Output: [6, 7] Explanation: Node 5 is at the same level as nodes 4, 6, and 7. Among them, node 4 is a sibling of 5 since both have the same parent (2), so it is not considered a cousin. Nodes 6 and 7 have a different parent (3), making them cousins of node 5. Therefore, the output is 6 7.
Input: root[] = [9, 5, N], node = 5 9 / 5 Output: [-1] Explanation: There are no other nodes at the same level as node 5. Therefore, the output is [-1].
[Naive Approach] Using Two DFS Traversals - O(n) Time and O(h) Space
The idea is to first perform a DFS to find the level and parent of the given node. Then perform another DFS to visit every node again. Whenever a node is found at the target level with a different parent, add it to the answer. If no such node exists, return [-1].
Working of the Approach:
Perform a DFS to find the level and parent of the given target node.
Traverse the tree again using DFS and visit every node. If a node is at the same level as the target and has a different parent, add it to the answer.
Ignore nodes that share the same parent as the target since they are siblings, not cousins.
After the traversal, if no cousin is found, return [-1]; otherwise, return the collected cousin nodes.
C++
#include<iostream>#include<vector>usingnamespacestd;classNode{public:intdata;Node*left;Node*right;Node(intval){data=val;left=right=nullptr;}};// Find the level and parent of the target nodevoidfindNode(Node*root,Node*parent,Node*target,intlevel,int&targetLevel,Node*&targetParent){if(root==nullptr)return;// Target node foundif(root==target){targetLevel=level;targetParent=parent;return;}// Search in left subtreefindNode(root->left,root,target,level+1,targetLevel,targetParent);// Search in right subtreefindNode(root->right,root,target,level+1,targetLevel,targetParent);}// Collect all cousin nodesvoidfindCousins(Node*root,Node*parent,intlevel,inttargetLevel,Node*targetParent,vector<int>&ans){if(root==nullptr)return;// If current node is at target levelif(level==targetLevel){// Ignore siblings of the target nodeif(parent!=targetParent)ans.push_back(root->data);return;}// Traverse left subtreefindCousins(root->left,root,level+1,targetLevel,targetParent,ans);// Traverse right subtreefindCousins(root->right,root,level+1,targetLevel,targetParent,ans);}vector<int>getCousins(Node*root,Node*node){// Root has no cousinsif(root==node)return{-1};inttargetLevel=-1;Node*targetParent=nullptr;// Find the level and parent of target nodefindNode(root,nullptr,node,0,targetLevel,targetParent);vector<int>ans;// Collect all cousin nodesfindCousins(root,nullptr,0,targetLevel,targetParent,ans);// No cousins existif(ans.empty())return{-1};returnans;}intmain(){// Construct the binary treeNode*root=newNode(1);root->left=newNode(2);root->right=newNode(3);root->left->left=newNode(4);root->left->right=newNode(5);root->right->left=newNode(6);root->right->right=newNode(7);Node*node=root->left->right;vector<int>ans=getCousins(root,node);cout<<"[";for(inti=0;i<ans.size();i++){cout<<ans[i];if(i+1<ans.size())cout<<", ";}cout<<"]";return0;}
Java
importjava.util.*;classNode{intdata;Nodeleft;Noderight;Node(intval){data=val;left=right=null;}}publicclassGFG{// Find the level and parent of the target nodestaticvoidfindNode(Noderoot,Nodeparent,Nodetarget,intlevel,int[]targetLevel,Node[]targetParent){if(root==null)return;// Target node foundif(root==target){targetLevel[0]=level;targetParent[0]=parent;return;}// Search in left subtreefindNode(root.left,root,target,level+1,targetLevel,targetParent);// Search in right subtreefindNode(root.right,root,target,level+1,targetLevel,targetParent);}// Collect all cousin nodesstaticvoidfindCousins(Noderoot,Nodeparent,intlevel,inttargetLevel,NodetargetParent,ArrayList<Integer>ans){if(root==null)return;// If current node is at target levelif(level==targetLevel){// Ignore siblings of the target nodeif(parent!=targetParent)ans.add(root.data);return;}// Traverse left subtreefindCousins(root.left,root,level+1,targetLevel,targetParent,ans);// Traverse right subtreefindCousins(root.right,root,level+1,targetLevel,targetParent,ans);}staticArrayList<Integer>getCousins(Noderoot,Nodenode){// Root has no cousinsif(root==node)returnnewArrayList<>(Arrays.asList(-1));int[]targetLevel={-1};Node[]targetParent={null};// Find the level and parent of target nodefindNode(root,null,node,0,targetLevel,targetParent);ArrayList<Integer>ans=newArrayList<>();// Collect all cousin nodesfindCousins(root,null,0,targetLevel[0],targetParent[0],ans);// No cousins existif(ans.isEmpty())returnnewArrayList<>(Arrays.asList(-1));returnans;}publicstaticvoidmain(String[]args){// Construct the binary treeNoderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.left.left=newNode(4);root.left.right=newNode(5);root.right.left=newNode(6);root.right.right=newNode(7);Nodenode=root.left.right;ArrayList<Integer>ans=getCousins(root,node);System.out.print("[");for(inti=0;i<ans.size();i++){System.out.print(ans.get(i));if(i+1<ans.size())System.out.print(", ");}System.out.println("]");}}
Python
classNode:def__init__(self,val):self.data=valself.left=Noneself.right=None# Find the level and parent of the target nodedeffindNode(root,parent,target,level,targetLevel,targetParent):ifnotroot:return# Target node foundifroot==target:targetLevel[0]=leveltargetParent[0]=parentreturn# Search in left subtreefindNode(root.left,root,target,level+1,targetLevel,targetParent)# Search in right subtreefindNode(root.right,root,target,level+1,targetLevel,targetParent)# Collect all cousin nodesdeffindCousins(root,parent,level,targetLevel,targetParent,ans):ifnotroot:return# If current node is at target leveliflevel==targetLevel:# Ignore siblings of the target nodeifparent!=targetParent:ans.append(root.data)return# Traverse left subtreefindCousins(root.left,root,level+1,targetLevel,targetParent,ans)# Traverse right subtreefindCousins(root.right,root,level+1,targetLevel,targetParent,ans)defgetCousins(root,node):# Root has no cousinsifroot==node:return[-1]targetLevel=[-1]targetParent=[None]# Find the level and parent of target nodefindNode(root,None,node,0,targetLevel,targetParent)ans=[]# Collect all cousin nodesfindCousins(root,None,0,targetLevel[0],targetParent[0],ans)# No cousins existifnotans:return[-1]returnansif__name__=='__main__':# Construct the binary treeroot=Node(1)root.left=Node(2)root.right=Node(3)root.left.left=Node(4)root.left.right=Node(5)root.right.left=Node(6)root.right.right=Node(7)node=root.left.rightans=getCousins(root,node)print('[',end='')foriinrange(len(ans)):print(ans[i],end='')ifi+1<len(ans):print(', ',end='')print(']')
C#
usingSystem;usingSystem.Collections.Generic;classNode{publicintdata;publicNodeleft;publicNoderight;publicNode(intval){data=val;left=right=null;}}classGFG{// Find the level and parent of the target nodevoidFindNode(Noderoot,Nodeparent,Nodetarget,intlevel,refinttargetLevel,refNodetargetParent){if(root==null)return;// Target node foundif(root==target){targetLevel=level;targetParent=parent;return;}// Search in left subtreeFindNode(root.left,root,target,level+1,reftargetLevel,reftargetParent);// Search in right subtreeFindNode(root.right,root,target,level+1,reftargetLevel,reftargetParent);}// Collect all cousin nodesvoidFindCousins(Noderoot,Nodeparent,intlevel,inttargetLevel,NodetargetParent,List<int>ans){if(root==null)return;// If current node is at target levelif(level==targetLevel){// Ignore siblings of the target nodeif(parent!=targetParent)ans.Add(root.data);return;}// Traverse left subtreeFindCousins(root.left,root,level+1,targetLevel,targetParent,ans);// Traverse right subtreeFindCousins(root.right,root,level+1,targetLevel,targetParent,ans);}publicList<int>getCousins(Noderoot,Nodenode){// Root has no cousinsif(root==node)returnnewList<int>{-1};inttargetLevel=-1;NodetargetParent=null;// Find the level and parent of target nodeFindNode(root,null,node,0,reftargetLevel,reftargetParent);List<int>ans=newList<int>();// Collect all cousin nodesFindCousins(root,null,0,targetLevel,targetParent,ans);// No cousins existif(ans.Count==0)returnnewList<int>{-1};returnans;}staticvoidMain(){// Construct the binary treeNoderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.left.left=newNode(4);root.left.right=newNode(5);root.right.left=newNode(6);root.right.right=newNode(7);Nodenode=root.left.right;GFGobj=newGFG();List<int>ans=obj.getCousins(root,node);Console.Write("[");for(inti=0;i<ans.Count;i++){Console.Write(ans[i]);if(i+1<ans.Count)Console.Write(", ");}Console.WriteLine("]");}}
JavaScript
classNode{constructor(val){this.data=val;this.left=null;this.right=null;}}// Find the level and parent of the target nodefunctionfindNode(root,parent,target,level,targetInfo){if(root===null)return;// Target node foundif(root.data===target){targetInfo.level=level;targetInfo.parent=parent?parent.data:null;return;}// Search in left subtreefindNode(root.left,root,target,level+1,targetInfo);// Search in right subtreefindNode(root.right,root,target,level+1,targetInfo);}// Collect all cousin nodesfunctionfindCousins(root,parent,level,targetLevel,targetParent,ans){if(root===null)return;// If current node is at target levelif(level===targetLevel){// Ignore siblings of the target nodeif((parent?parent.data:null)!==targetParent)ans.push(root.data);return;}// Traverse left subtreefindCousins(root.left,root,level+1,targetLevel,targetParent,ans);// Traverse right subtreefindCousins(root.right,root,level+1,targetLevel,targetParent,ans);}functiongetCousins(root,node){// Root has no cousinsif(root.data===node)return[-1];lettargetInfo={level:-1,parent:null};// Find the level and parent of target nodefindNode(root,null,node,0,targetInfo);letans=[];// Collect all cousin nodesfindCousins(root,null,0,targetInfo.level,targetInfo.parent,ans);// No cousins existif(ans.length===0)return[-1];returnans;}// Construct the binary treeletroot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.left.left=newNode(4);root.left.right=newNode(5);root.right.left=newNode(6);root.right.right=newNode(7);letnode=5;letans=getCousins(root,node);process.stdout.write("[");for(leti=0;i<ans.length;i++){process.stdout.write(ans[i].toString());if(i+1<ans.length)process.stdout.write(", ");}process.stdout.write("]");
Output
[6, 7]
[Expected Approach] Using Single Level Order Traversal - O(n) Time and O(n) Space
The idea is to perform a single level order traversal of the binary tree. While processing each level, check whether the current node is the parent of the target node. If it is, skip adding both the target node and its sibling to the queue. Otherwise, insert its children normally. After completing that level, the queue contains only the cousins of the target node.
Let us understand with an example: Input: root[] = [1, 2, 3, 4, 5, 6, 7], node = 5
Start the level order traversal from the root node 1. Since it is not the parent of the target node 5, add its children 2 and 3 to the queue.
Process the next level containing 2 and 3. Node 2 is the parent of 5, so do not add its children (4 and 5) to the queue. For node 3, add its children 6 and 7 to the queue.
After completing this level, the parent of the target node has been found, so stop the traversal.
The queue now contains only 6 and 7, which are the nodes at the same level as 5 but have a different parent.
Return [6, 7] as the cousins of the given node.
C++
#include<iostream>#include<queue>#include<vector>usingnamespacestd;classNode{public:intdata;Node*left;Node*right;Node(intval){data=val;left=right=nullptr;}};vector<int>getCousins(Node*root,Node*node){vector<int>ans;// Root has no cousinsif(root==node){ans.push_back(-1);returnans;}queue<Node*>q;boolfound=false;q.push(root);// Traverse the tree level by levelwhile(!q.empty()&&!found){intsize_=q.size();while(size_--){Node*curr=q.front();q.pop();// If current node is the parent of target node,// skip adding the target node and its siblingif(curr->left==node||curr->right==node){found=true;}else{// Push left childif(curr->left)q.push(curr->left);// Push right childif(curr->right)q.push(curr->right);}}}// Remaining nodes in the queue are cousinsif(!q.empty()){while(!q.empty()){ans.push_back(q.front()->data);q.pop();}}else{ans.push_back(-1);}returnans;}intmain(){// Construct the binary treeNode*root=newNode(1);root->left=newNode(2);root->right=newNode(3);root->left->left=newNode(4);root->left->right=newNode(5);root->right->left=newNode(6);root->right->right=newNode(7);Node*node=root->left->right;vector<int>ans=getCousins(root,node);cout<<"[";for(inti=0;i<ans.size();i++){cout<<ans[i];if(i+1<ans.size())cout<<", ";}cout<<"]";return0;}
Java
importjava.util.*;classNode{intdata;Nodeleft;Noderight;Node(intval){data=val;left=right=null;}}publicclassGFG{staticArrayList<Integer>getCousins(Noderoot,Nodenode){ArrayList<Integer>ans=newArrayList<>();// Root has no cousinsif(root==node){ans.add(-1);returnans;}Queue<Node>q=newLinkedList<>();booleanfound=false;q.offer(root);// Traverse the tree level by levelwhile(!q.isEmpty()&&!found){intsize_=q.size();while(size_-->0){Nodecurr=q.poll();// If current node is the parent of target// node, skip adding the target node and its// siblingif(curr.left==node||curr.right==node){found=true;}else{// Push left childif(curr.left!=null)q.offer(curr.left);// Push right childif(curr.right!=null)q.offer(curr.right);}}}// Remaining nodes in the queue are cousinsif(!q.isEmpty()){while(!q.isEmpty()){ans.add(q.poll().data);}}else{ans.add(-1);}returnans;}publicstaticvoidmain(String[]args){// Construct the binary treeNoderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.left.left=newNode(4);root.left.right=newNode(5);root.right.left=newNode(6);root.right.right=newNode(7);Nodenode=root.left.right;ArrayList<Integer>ans=getCousins(root,node);System.out.print("[");for(inti=0;i<ans.size();i++){System.out.print(ans.get(i));if(i+1<ans.size())System.out.print(", ");}System.out.print("]");}}
Python
fromcollectionsimportdequeclassNode:def__init__(self,val):self.data=valself.left=Noneself.right=NonedefgetCousins(root,node):ans=[]# Root has no cousinsifroot==node:ans.append(-1)returnansq=deque()found=Falseq.append(root)# Traverse the tree level by levelwhileqandnotfound:size_=len(q)for_inrange(size_):curr=q.popleft()# If current node is the parent of target node,# skip adding the target node and its siblingifcurr.left==nodeorcurr.right==node:found=Trueelse:# Push left childifcurr.leftisnotNone:q.append(curr.left)# Push right childifcurr.rightisnotNone:q.append(curr.right)# Remaining nodes in the queue are cousinsifq:whileq:ans.append(q.popleft().data)else:ans.append(-1)returnansif__name__=="__main__":# Construct the binary treeroot=Node(1)root.left=Node(2)root.right=Node(3)root.left.left=Node(4)root.left.right=Node(5)root.right.left=Node(6)root.right.right=Node(7)node=root.left.rightans=getCousins(root,node)print('[',end='')foriinrange(len(ans)):print(ans[i],end='')ifi+1<len(ans):print(', ',end='')print(']')
C#
usingSystem;usingSystem.Collections.Generic;classNode{publicintdata;publicNodeleft;publicNoderight;publicNode(intval){data=val;left=right=null;}}classGFG{staticList<int>getCousins(Noderoot,Nodenode){List<int>ans=newList<int>();// Root has no cousinsif(root==node){ans.Add(-1);returnans;}Queue<Node>q=newQueue<Node>();boolfound=false;q.Enqueue(root);// Traverse the tree level by levelwhile(q.Count>0&&!found){intsize_=q.Count;while(size_-->0){Nodecurr=q.Dequeue();// If current node is the parent of target// node, skip adding the target node and its// siblingif(curr.left==node||curr.right==node){found=true;}else{// Push left childif(curr.left!=null)q.Enqueue(curr.left);// Push right childif(curr.right!=null)q.Enqueue(curr.right);}}}// Remaining nodes in the queue are cousinsif(q.Count>0){while(q.Count>0){ans.Add(q.Dequeue().data);}}else{ans.Add(-1);}returnans;}staticvoidMain(){// Construct the binary treeNoderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.left.left=newNode(4);root.left.right=newNode(5);root.right.left=newNode(6);root.right.right=newNode(7);Nodenode=root.left.right;List<int>ans=getCousins(root,node);Console.Write("[");for(inti=0;i<ans.Count;i++){Console.Write(ans[i]);if(i+1<ans.Count)Console.Write(", ");}Console.Write("]");}}
JavaScript
classNode{constructor(val){this.data=val;this.left=null;this.right=null;}}functiongetCousins(root,node){letans=[];// Root has no cousinsif(root===node){ans.push(-1);returnans;}letq=[];letfound=false;q.push(root);// Traverse the tree level by levelwhile(q.length>0&&!found){letsize_=q.length;for(leti=0;i<size_;i++){letcurr=q.shift();// If current node is the parent of target node,// skip adding the target node and its siblingif(curr.left===node||curr.right===node){found=true;}else{// Push left childif(curr.left!==null){q.push(curr.left);}// Push right childif(curr.right!==null){q.push(curr.right);}}}}// Remaining nodes in the queue are cousinsif(q.length>0){while(q.length>0){ans.push(q[0].data);q.shift();}}else{ans.push(-1);}returnans;}// Construct the binary treeletroot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.left.left=newNode(4);root.left.right=newNode(5);root.right.left=newNode(6);root.right.right=newNode(7);letnode=root.left.right;letans=getCousins(root,node);console.log("[");for(leti=0;i<ans.length;i++){console.log(ans[i]);if(i+1<ans.length){console.log(", ");}}console.log("]");