# check if value exists in level | python3 implementation of the approach ; class containing left and right child of current node and key value ; function to locate which level to check for the existence of key . ; if the key is less than the root , it will certainly not exist in the tree because tree is level - order sorted ; if the key is equal to the root then simply return 0 ( zero 'th level) ; if the key is found in any leftmost element then simply return true no need for any extra searching ; if key lies between the root data and the left child 's data or if key is greater  than root data and there is no level  underneath it, return the current level ; function to traverse a binary encoded path and return the value encountered after traversal . ; go left ; incomplete path ; go right ; incomplete path ; return the data at the node ; function to generate gray code of corresponding binary number of integer i ; create new arraylist to store the gray code ; reverse the encoding till here ; leftmost digits are filled with 0 ; function to search the key in a particular level of the tree . ; find the middle index ; encode path from root to this index in the form of 0 s and 1 s where 0 means left and 1 means right ; traverse the path in the tree and check if the key is found ; if path is incomplete ; check the left part of the level ; check the right part of the level ; check the left part of the level ; key not found in that level ; function that returns true if the key is found in the tree ; find the level where the key may lie ; if level is - 1 then return false ; if level is - 2 i . e . key was found in any leftmost element then simply return true ; apply binary search on the elements of that level ; 

from sys import maxsize
from collections import deque
INT_MIN = -maxsize


class Node:
    def __init__(self, data):
        self .data = data
        self .left = None
        self .right = None


def findLevel(root: Node, data: int) -> int:
    if (data < root .data):
        return -1
    if (data == root .data):
        return 0
    cur_level = 0
    while True:
        cur_level += 1
        root = root .left
        if (root .data == data):
            return -2
        if (root .data < data and (root .left is None or root .left .data > data)):
            break
    return cur_level


def traversePath(root: Node, path: list) -> int:
    for i in range(len(path)):
        direction = path[i]
        if (direction == 0):
            if (root .left is None):
                return -1
            root = root .left
        else:
            if (root .right is None):
                return -1
            root = root .right
    return root .data


def generateGray(n: int, x: int) -> list:
    gray = []
    i = 0
    while (x > 0):
        gray .append(x % 2)
        x = x / 2
        i += 1
    gray .reverse()
    for j in range(n - i):
        gray .insert(0, gray[0])
    return gray


def binarySearch(
        root: Node,
        start: int,
        end: int,
        data: int,
        level: int) -> bool:
    if (end >= start):
        mid = (start + end) / 2
        encoding = generateGray(level, mid)
        element_found = traversePath(root, encoding)
        if (element_found == -1):
            return binarySearch(root, start, mid - 1, data, level)
        if (element_found == data):
            return True
        if (element_found < data):
            return binarySearch(root, mid + 1, end, data, level)
        else:
            return binarySearch(root, start, mid - 1, data, level)
    return False


def findKey(root: Node, data: int) -> bool:
    level = findLevel(root, data)
    if (level == -1):
        return False
    if (level == -2):
        return True
    return binarySearch(root, 0, int(pow(2, level) - 1), data, level)


if __name__ == "__main__":
    root = Node(5)
    root .left = Node(8)
    root .right = Node(10)
    root .left .left = Node(13)
    root .left .right = Node(23)
    root .right .left = Node(25)
    root .right .right = Node(30)
    root .left .left .left = Node(32)
    root .left .left .right = Node(40)
    root .left .right .left = Node(50)
    arr = [5, 8, 9]
    n = len(arr)
    for i in range(n):
        if (findKey(root, arr[i])):
            print("Yes")
        else:
            print("No")

# Expected output:
Yes
Yes
No