Given a Binary Search Tree of size N, find the Median of its Node values.
Example 1:
Input:
       6
     /   \
   3      8   
 /  \    /  \
1    4  7    9
Output: 6
Explanation: Inorder of Given BST will be:
1, 3, 4, 6, 7, 8, 9. So, here median will 6.
Example 2:
Input:
       6
     /   \
   3      8   
 /   \    /   
1    4   7   
Output: 5
Explanation:Inorder of Given BST will be:
1, 3, 4, 6, 7, 8. So, here median will
(4 + 6)/2 = 10/2 = 5.
 
Your Task:
You don't need to read input or print anything. Your task is to complete the function findMedian() which takes the root of the Binary Search Tree as input and returns the Median of Node values in the given BST.
Median of the BST is:
	If number of nodes are even: then median = (N/2 th node + (N/2)+1 th node)/2
	If number of nodes are odd : then median = (N+1)/2th node.
Expected Time Complexity: O(N).
Expected Auxiliary Space: O(Height of the Tree).
Constraints:
1<=N<=1000

Source: geeksforgeeks | Difficulty: EASY
Tags: Data structures

Graph traversal

Range queries

Starter code: #User function Template for python3

def findMedian(root):
    # code here
    # return the median


Solutions:
def count_nodes(root):
	cnt = 0
	temp = root
	while temp:
		if temp.left is None:
			cnt += 1
			temp = temp.right
		else:
			pred = temp.left
			while pred.right and pred.right != temp:
				pred = pred.right
			if pred.right is None:
				pred.right = temp
				temp = temp.left
			else:
				pred.right = None
				cnt += 1
				temp = temp.right
	return cnt

def get_ith_node(root, i):
	data = root.data
	temp = root
	while temp:
		if temp.left is None:
			i -= 1
			if i == 0:
				data = temp.data
			temp = temp.right
		else:
			pred = temp.left
			while pred.right and pred.right != temp:
				pred = pred.right
			if pred.right is None:
				pred.right = temp
				temp = temp.left
			else:
				pred.right = None
				i -= 1
				if i == 0:
					data = temp.data
				temp = temp.right
	return data

def findMedian(root):
	cnt = count_nodes(root)
	ans = root.data
	if cnt % 2 != 0:
		mid = cnt // 2
		ans = get_ith_node(root, mid + 1)
	else:
		mid = cnt // 2
		data_1 = get_ith_node(root, mid)
		data_2 = get_ith_node(root, mid + 1)
		ans = (data_1 + data_2) / 2
	return int(ans) if ans == int(ans) else ans


def count_nodes(root, cnt):
	if root is None:
		return
	count_nodes(root.left, cnt)
	cnt[0] += 1
	count_nodes(root.right, cnt)

def get_ith_node(root, i, data):
	try:
		if root is None:
			return
		get_ith_node(root.left, i, data)
		i[0] -= 1
		if i[0] == 0:
			data[0] = root.data
			return
		get_ith_node(root.right, i, data)
	except Exception as e:
		print(e)

def findMedian(root):
	cnt = [0]
	count_nodes(root, cnt)
	ans = root.data
	if cnt[0] % 2 != 0:
		mid = cnt[0] // 2
		data = [root.data]
		get_ith_node(root, [mid + 1], data)
		ans = data[0]
	else:
		mid = cnt[0] // 2
		data_1 = [root.data]
		get_ith_node(root, [mid], data_1)
		data_2 = [root.data]
		get_ith_node(root, [mid + 1], data_2)
		ans = (data_1[0] + data_2[0]) / 2
	return int(ans) if ans == int(ans) else ans