Given a perfect binary tree, print nodes of middle level without computing its height. A perfect binary tree is a binary tree in which all interior nodes have two children and all leaves have the same depth or same level.

Output : 4 5 6 7
The idea is similar to method 2 of finding middle of singly linked list.
Use fast and slow (or tortoise) pointers in each route of the tree.
- Advance fast pointer towards leaf by 2.
- Advance slow pointer towards lead by 1.
- If fast pointer reaches the leaf print value at the slow pointer
- Check if the fast->left->left exists, then recursively move slow pointer by one step and fast pointer by two steps.
- If the fast->left->left doesn't exist (in case of even number of levels), the move both the pointers by one step.
Implementation:
#include <bits/stdc++.h>
using namespace std;
/* A binary tree node has key, pointer to left
child and a pointer to right child */
struct Node {
int key;
struct Node *left, *right;
};
/* To create a newNode of tree and return pointer */
struct Node* newNode(int key)
{
Node* temp = new Node;
temp->key = key;
temp->left = temp->right = NULL;
return (temp);
}
// Takes two parameters - same initially and
// calls recursively
void printMiddleLevelUtil(Node* a, Node* b)
{
// Base case e
if (a == NULL || b == NULL)
return;
// Fast pointer has reached the leaf so print
// value at slow pointer
if ((b->left == NULL) && (b->right == NULL)) {
cout << a->key << " ";
return;
}
// Recursive call
// root.left.left and root.left.right will
// print same value
// root.right.left and root.right.right
// will print same value
// So we use any one of the condition
if (b->left->left) {
printMiddleLevelUtil(a->left, b->left->left);
printMiddleLevelUtil(a->right, b->left->left);
}
else {
printMiddleLevelUtil(a->left, b->left);
printMiddleLevelUtil(a->right, b->left);
}
}
// Main printing method that take a Tree as input
void printMiddleLevel(Node* node)
{
printMiddleLevelUtil(node, node);
}
// Driver program to test above functions
int main()
{
Node* n1 = newNode(1);
Node* n2 = newNode(2);
Node* n3 = newNode(3);
Node* n4 = newNode(4);
Node* n5 = newNode(5);
Node* n6 = newNode(6);
Node* n7 = newNode(7);
n2->left = n4;
n2->right = n5;
n3->left = n6;
n3->right = n7;
n1->left = n2;
n1->right = n3;
printMiddleLevel(n1);
}
// This code is contributed by Prasad Kshirsagar
// Tree node definition
class Node {
public int key;
public Node left;
public Node right;
public Node(int val)
{
this.left = null;
this.right = null;
this.key = val;
}
}
public class PrintMiddle
{
// Takes two parameters - same initially and
// calls recursively
private static void printMiddleLevelUtil(Node a, Node b)
{
// Base case e
if (a == null || b == null)
return;
// Fast pointer has reached the leaf so print
// value at slow pointer
if ((b.left == null) && (b.right == null))
{
System.out.print(a.key + " ");
return;
}
// Recursive call
// root.left.left and root.left.right will
// print same value
// root.right.left and root.right.right
// will print same value
// So we use any one of the condition
if (b.left.left!=null)
{
printMiddleLevelUtil(a.left, b.left.left);
printMiddleLevelUtil(a.right, b.left.left);
}
else
{
printMiddleLevelUtil(a.left, b.left);
printMiddleLevelUtil(a.right, b.left);
}
}
// Main printing method that take a Tree as input
public static void printMiddleLevel(Node node)
{
printMiddleLevelUtil(node, node);
}
// Driver code
public static void main(String[] args)
{
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
Node n4 = new Node(4);
Node n5 = new Node(5);
Node n6 = new Node(6);
Node n7 = new Node(7);
n2.left = n4;
n2.right = n5;
n3.left = n6;
n3.right = n7;
n1.left = n2;
n1.right = n3;
printMiddleLevel(n1);
}
}
''' A binary tree node has key, pointer to left
child and a pointer to right child '''
class Node:
def __init__(self, key):
self.key=key
self.left = None
self.right = None
# To create a newNode of tree and return pointer
def newNode(key):
temp = Node(key)
return temp
# Takes two parameters - same initially and
# calls recursively
def printMiddleLevelUtil(a, b):
# Base case e
if (a == None or b == None):
return;
# Fast pointer has reached the leaf so print
# value at slow pointer
if ((b.left == None) and (b.right == None)):
print(a.key, end=' ')
return;
# Recursive call
# root.left.left and root.left.right will
# print same value
# root.right.left and root.right.right
# will print same value
# So we use any one of the condition
if (b.left.left):
printMiddleLevelUtil(a.left, b.left.left);
printMiddleLevelUtil(a.right, b.left.left);
else:
printMiddleLevelUtil(a.left, b.left);
printMiddleLevelUtil(a.right, b.left);
# Main printing method that take a Tree as input
def printMiddleLevel(node):
printMiddleLevelUtil(node, node);
# Driver program to test above functions
if __name__=='__main__':
n1 = newNode(1);
n2 = newNode(2);
n3 = newNode(3);
n4 = newNode(4);
n5 = newNode(5);
n6 = newNode(6);
n7 = newNode(7);
n2.left = n4;
n2.right = n5;
n3.left = n6;
n3.right = n7;
n1.left = n2;
n1.right = n3;
printMiddleLevel(n1);
# This code is contributed by rutvik_56
using System;
// Tree node definition
public class Node {
public int key;
public Node left;
public Node right;
public Node(int val)
{
this.left = null;
this.right = null;
this.key = val;
}
}
public class PrintMiddle
{
// Takes two parameters - same initially and
// calls recursively
private static void printMiddleLevelUtil(Node a, Node b)
{
// Base case e
if (a == null || b == null)
return;
// Fast pointer has reached the leaf so print
// value at slow pointer
if ((b.left == null) && (b.right == null))
{
Console.Write(a.key + " ");
return;
}
// Recursive call
// root.left.left and root.left.right will
// print same value
// root.right.left and root.right.right
// will print same value
// So we use any one of the condition
if (b.left.left!=null)
{
printMiddleLevelUtil(a.left, b.left.left);
printMiddleLevelUtil(a.right, b.left.left);
}
else
{
printMiddleLevelUtil(a.left, b.left);
printMiddleLevelUtil(a.right, b.left);
}
}
// Main printing method that take a Tree as input
public static void printMiddleLevel(Node node)
{
printMiddleLevelUtil(node, node);
}
// Driver code
public static void Main(String[] args)
{
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
Node n4 = new Node(4);
Node n5 = new Node(5);
Node n6 = new Node(6);
Node n7 = new Node(7);
n2.left = n4;
n2.right = n5;
n3.left = n6;
n3.right = n7;
n1.left = n2;
n1.right = n3;
printMiddleLevel(n1);
}
}
// This code is contributed by Amit Katiyar
<script>
// Tree node definition
class Node
{
constructor(val) {
this.left = null;
this.right = null;
this.key = val;
}
}
// Takes two parameters - same initially and
// calls recursively
function printMiddleLevelUtil(a, b)
{
// Base case e
if (a == null || b == null)
return;
// Fast pointer has reached the leaf so print
// value at slow pointer
if ((b.left == null) && (b.right == null))
{
document.write(a.key + " ");
return;
}
// Recursive call
// root.left.left and root.left.right will
// print same value
// root.right.left and root.right.right
// will print same value
// So we use any one of the condition
if (b.left.left != null)
{
printMiddleLevelUtil(a.left, b.left.left);
printMiddleLevelUtil(a.right, b.left.left);
}
else
{
printMiddleLevelUtil(a.left, b.left);
printMiddleLevelUtil(a.right, b.left);
}
}
// Main printing method that take a Tree as input
function printMiddleLevel(node)
{
printMiddleLevelUtil(node, node);
}
let n1 = new Node(1);
let n2 = new Node(2);
let n3 = new Node(3);
let n4 = new Node(4);
let n5 = new Node(5);
let n6 = new Node(6);
let n7 = new Node(7);
n2.left = n4;
n2.right = n5;
n3.left = n6;
n3.right = n7;
n1.left = n2;
n1.right = n3;
printMiddleLevel(n1);
// This code is contributed by suresh07.
</script>
Output
2 3
Time Complexity: O(n), As we are doing normal preorder traversal, every node can be visited atmost once.
Auxiliary Space: O(h), Here h is the height of the tree and the extra space is used due to recursive function call stack.
You could hit me an email - kishan020696@gmail.com