Find value K in given Complete Binary Tree with values indexed from 1 to N
Last Updated :
27 Mar, 2023
Given a complete binary tree with values indexed from 1 to N and a key K. The task is to check whether a key exists in the tree or not. Print "true" if the key exists, otherwise print "false".
Complete Binary Tree: A Binary Tree is a complete Binary Tree if all the levels are completely filled except possibly the last level and the last level has all keys as left as possible
Examples:
Input: K = 2
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
Output: true
Input: K = 11
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
Output: false
Naive Approach: The simplest approach would be to simply traverse the entire tree and check if the key exists in the tree or not.
Time Complexity: O(N)
Auxiliary Space: O(1)
Efficient Approach: The approach is based on the idea that the tree is a complete binary tree and the nodes are indexed from 1 to N starting from the top. So we can track down the path going from the root to the key if at all the key existed. Below are the steps:
- For a complete binary tree given node i, its children will be 2*i and 2*i + 1. Therefore, given node i, its parent node will be i/2.
- Iteratively find out the parent of the key until the root node of the tree is found, and store the steps in an array steps[] as -1 for left and 1 for right (Left means that the current node is the left child of its parent and right means the current node is the right child of its parent).
- Now transverse the tree according to the moves stored in the array steps[]. If the entire array is successfully transversed, it means that the key exists in the tree so print "True", otherwise print "False".
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// Class containing left
// and right child of current node
// and key value
class Node {
public:
int data;
Node* left;
Node* right;
Node(int item)
{
data = item;
left = NULL;
right = NULL;
}
};
// Function to store the
// list of the directions
vector<int> findSteps(Node* root, int data)
{
vector<int> steps;
// While the root is not found
while (data != 1) {
// If it is the right
// child of its parent
if (data / 2.0 > data / 2) {
// Add right step (1)
steps.push_back(1);
}
else {
// Add left step (-1)
steps.push_back(-1);
}
int parent = data / 2;
// Repeat the same
// for its parent
data = parent;
}
// Reverse the steps list
reverse(steps.begin(), steps.end());
// Return the steps
return steps;
}
// Function to find
// if the key is present or not
bool findKey(Node* root, int data)
{
// Get the steps to be followed
vector<int> steps = findSteps(root, data);
// Taking one step at a time
for (auto cur_step : steps)
{
// Go left
if (cur_step == -1) {
// If left child does
// not exist return false
if (root->left == NULL)
return false;
root = root->left;
}
// Go right
else {
// If right child does
// not exist return false
if (root->right == NULL)
return false;
root = root->right;
}
}
// If the entire array of steps
// has been successfully
// traversed
return true;
}
int main()
{
/* Consider the following complete binary tree
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
*/
Node* root = new Node(1);
root->left = new Node(2);
root->right = new Node(3);
root->left->left = new Node(4);
root->left->right = new Node(5);
root->right->left = new Node(6);
root->right->right = new Node(7);
root->left->left->left = new Node(8);
root->left->left->right = new Node(9);
root->left->right->left = new Node(10);
// Function Call
cout<<boolalpha<<findKey(root, 7)<<endl;
}
// This code is contributed by Pushpesh Raj.
Java
// Java program for the above approach
import java.util.*;
import java.io.*;
// Class containing left
// and right child of current node
// and key value
class Node {
int data;
Node left, right;
public Node(int item)
{
data = item;
left = null;
right = null;
}
}
class Solution {
// Function to store the
// list of the directions
public static ArrayList<Integer>
findSteps(Node root, int data)
{
ArrayList<Integer> steps
= new ArrayList<Integer>();
// While the root is not found
while (data != 1) {
// If it is the right
// child of its parent
if (data / 2.0 > data / 2) {
// Add right step (1)
steps.add(1);
}
else {
// Add left step (-1)
steps.add(-1);
}
int parent = data / 2;
// Repeat the same
// for its parent
data = parent;
}
// Reverse the steps list
Collections.reverse(steps);
// Return the steps
return steps;
}
// Function to find
// if the key is present or not
public static boolean
findKey(Node root, int data)
{
// Get the steps to be followed
ArrayList<Integer> steps
= findSteps(root, data);
// Taking one step at a time
for (Integer cur_step : steps) {
// Go left
if (cur_step == -1) {
// If left child does
// not exist return false
if (root.left == null)
return false;
root = root.left;
}
// Go right
else {
// If right child does
// not exist return false
if (root.right == null)
return false;
root = root.right;
}
}
// If the entire array of steps
// has been successfully
// traversed
return true;
}
public static void main(String[] args)
{
/* Consider the following complete binary tree
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
*/
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(6);
root.right.right = new Node(7);
root.left.left.left = new Node(8);
root.left.left.right = new Node(9);
root.left.right.left = new Node(10);
// Function Call
System.out.println(findKey(root, 7));
}
}
Python3
# Python program to implement above approach
# Class containing left
# and right child of current node
# and key value
class Node:
def __init__(self,item):
self.data = item
self.left = None
self.right = None
# Function to store the
# list of the directions
def findSteps(root,data):
steps = []
# While the root is not found
while (data != 1):
# If it is the right
# child of its parent
if (data / 2 > data // 2):
# Add right step (1)
steps.append(1)
else:
# Add left step (-1)
steps.append(-1)
parent = data // 2
# Repeat the same
# for its parent
data = parent
# Reverse the steps list
steps = steps[::-1]
# Return the steps
return steps
# Function to find
# if the key is present or not
def findKey(root,data):
# Get the steps to be followed
steps = findSteps(root, data)
# Taking one step at a time
for cur_step in steps:
# Go left
if (cur_step == -1):
# If left child does
# not exist return False
if (root.left == None):
return False
root = root.left
# Go right
else:
# If right child does
# not exist return False
if (root.right == None):
return False
root = root.right
# If the entire array of steps
# has been successfully
# traversed
return True
# driver code
# Consider the following complete binary tree
# 1
# / \
# 2 3
# / \ / \
# 4 5 6 7
# / \ /
# 8 9 10
#
root = 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)
root.left.left.left = Node(8)
root.left.left.right = Node(9)
root.left.right.left = Node(10)
# Function Call
print(findKey(root, 7))
# This code is contributed by shinjanpatra
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
// Class containing left
// and right child of current node
// and key value
class Node
{
public int data;
public Node left, right;
public Node(int item)
{
data = item;
left = right = null;
}
}
class Solution {
// Function to store the
// list of the directions
public static List<int>
findSteps(Node root, int data)
{
List<int> steps
= new List<int>();
// While the root is not found
while (data != 1) {
// If it is the right
// child of its parent
if (data / 2.0 > data / 2) {
// Add right step (1)
steps.Add(1);
}
else {
// Add left step (-1)
steps.Add(-1);
}
int parent = data / 2;
// Repeat the same
// for its parent
data = parent;
}
// Reverse the steps list
steps.Reverse();
// Return the steps
return steps;
}
// Function to find
// if the key is present or not
public static bool
findKey(Node root, int data)
{
// Get the steps to be followed
List<int> steps
= findSteps(root, data);
// Taking one step at a time
foreach (int cur_step in steps) {
// Go left
if (cur_step == -1) {
// If left child does
// not exist return false
if (root.left == null)
return false;
root = root.left;
}
// Go right
else {
// If right child does
// not exist return false
if (root.right == null)
return false;
root = root.right;
}
}
// If the entire array of steps
// has been successfully
// traversed
return true;
}
public static void Main()
{
/* Consider the following complete binary tree
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
*/
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(6);
root.right.right = new Node(7);
root.left.left.left = new Node(8);
root.left.left.right = new Node(9);
root.left.right.left = new Node(10);
// Function Call
Console.Write(findKey(root, 7));
}
}
JavaScript
<script>
// JavaScript program to implement above approach
// Class containing left
// and right child of current node
// and key value
class Node {
constructor(item)
{
this.data = item;
this.left = null;
this.right = null;
}
}
// Function to store the
// list of the directions
function findSteps(root,data)
{
let steps = [];
// While the root is not found
while (data != 1)
{
// If it is the right
// child of its parent
if (data / 2 > Math.floor(data / 2)) {
// Add right step (1)
steps.push(1);
}
else {
// Add left step (-1)
steps.push(-1);
}
let parent = Math.floor(data / 2);
// Repeat the same
// for its parent
data = parent;
}
// Reverse the steps list
steps.reverse();
// Return the steps
return steps;
}
// Function to find
// if the key is present or not
function findKey(root,data)
{
// Get the steps to be followed
let steps = findSteps(root, data);
// Taking one step at a time
for (let cur_step of steps) {
// Go left
if (cur_step == -1) {
// If left child does
// not exist return false
if (root.left == null)
return false;
root = root.left;
}
// Go right
else {
// If right child does
// not exist return false
if (root.right == null)
return false;
root = root.right;
}
}
// If the entire array of steps
// has been successfully
// traversed
return true;
}
// driver code
/* Consider the following complete binary tree
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
*/
let root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(6);
root.right.right = new Node(7);
root.left.left.left = new Node(8);
root.left.left.right = new Node(9);
root.left.right.left = new Node(10);
// Function Call
document.write(findKey(root, 7),"</br>");
// This code is contributed by shinjanpatra
</script>
Time Complexity: O(logN)
Auxiliary Space: O(logN)