Banana-Leopard/TASTY huggingface dataset:
# Python3 program to check if two BSTs contains
# same set of elements
 
# BST Node
class Node:
    def __init__(self):
        self.val = 0
        self.left = None
        self.right = None
 
# Utility function to create Node
def Node_(val1):
 
    temp = Node()
    temp.val = val1
    temp.left = temp.right = None
    return temp
 
s = {}
 
# function to insert elements of the
# tree to map m
def insertToHash(root):
 
    if (root == None):
        return
    insertToHash(root.left)
    s.add(root.data)
    insertToHash(root.right)
 
# function to check if the two BSTs contain
# same set of elements
def checkBSTs(root1, root2):
 
    # Base cases
    if (root1 != None and root2 != None) :
        return True
    if ((root1 == None and root2 != None) or
        (root1 != None and root2 == None)):
        return False
         
    # Create two hash sets and store
    # elements both BSTs in them.
    s1 = {}
    s2 = {}
    s = s1
    insertToHash(root1)
    s1 = s
    s = s2
    insertToHash(root2)
    s2 = s
     
    # Return True if both hash sets
    # contain same elements.
    return (s1 == (s2))
 
# Driver code
 
# First BST
root1 = Node_(15)
root1.left = Node_(10)
root1.right = Node_(20)
root1.left.left = Node_(5)
root1.left.right = Node_(12)
root1.right.right = Node_(25)
     
# Second BST
root2 = Node_(15)
root2.left = Node_(12)
root2.right = Node_(20)
root2.left.left = Node_(5)
root2.left.left.right = Node_(10)
root2.right.right = Node_(25)
     
# check if two BSTs have same set of elements
if (checkBSTs(root1, root2)):
    print("YES")
else:
    print("NO")
     
# This code is contributed by Arnab Kundu

Time complexity: linear
Space complexity: linear
# Python3 program to check if two BSTs contains
# same set of elements
 
# BST Node
class Node:
    def __init__(self):
        self.data = 0
        self.left = None
        self.right = None
 
# Utility function to create Node
def Node_(val1):
 
    temp = Node()
    temp.data = val1
    temp.left = temp.right = None
    return temp
 
v = []
 
# function to insert elements of the
# tree to map m
def storeInorder(root):
 
    if (root == None):
        return
    storeInorder(root.left)
    v.append(root.data)
    storeInorder(root.right)
 
# function to check if the two BSTs contain
# same set of elements
def checkBSTs(root1, root2):
 
    # Base cases
    if (root1 == None and root2 == None) :
        return True
    if ((root1 == None and root2 != None) or \
        (root1 != None and root2 == None)):
        return False
         
    # Create two hash sets and store
    # elements both BSTs in them.
    v1 = []
    v2 = []
    v = v1
    storeInorder(root1)
    v1 = v
    v = v2
    storeInorder(root2)
    v2 = v
     
    # Return True if both hash sets
    # contain same elements.
    return (v1 == v2)
 
# Driver code
 
# First BST
root1 = Node_(15)
root1.left = Node_(10)
root1.right = Node_(20)
root1.left.left = Node_(5)
root1.left.right = Node_(12)
root1.right.right = Node_(25)
     
# Second BST
root2 = Node_(15)
root2.left = Node_(12)
root2.right = Node_(20)
root2.left.left = Node_(5)
root2.left.left.right = Node_(10)
root2.right.right = Node_(25)
     
# check if two BSTs have same set of elements
if (checkBSTs(root1, root2)):
    print("YES")
else:
    print("NO")
     
# This code is contributed by SHUBHAMSINGH10

Time complexity: linear
Space complexity: linear
# Python3 implementation to count pairs
# from two BSTs whose sum is equal to a
# given  value x
 
# Structure of a node of BST
class getNode:
     
    def __init__(self, data):
         
        self.data = data
        self.left = None
        self.right = None
 
# Function to count pairs from two BSTs
# whose sum is equal to a given value x
def countPairs(root1, root2, x):
     
    # If either of the tree is empty
    if (root1 == None or root2 == None):
        return 0
 
    # Stack 'st1' used for the inorder
    # traversal of BST 1
    # stack 'st2' used for the reverse
    # inorder traversal of BST 2
    st1 = []
    st2 = []
 
    count = 3
 
    # The loop will break when either
    # of two traversals gets completed
    while (1):
         
        # To find next node in inorder
        # traversal of BST 1
        while (root1 != None):
            st1.append(root1)
            root1 = root1.left
 
        # To find next node in reverse
        # inorder traversal of BST 2
        while (root2 != None):
            st2.append(root2)
            root2 = root2.right
 
        # If either gets empty then corresponding
        # tree traversal is completed
        if (len(st1) or len(st2)):
            break
 
        top1 = st1[len(st1) - 1]
        top2 = st2[len(st2) - 1]
 
        # If the sum of the node's is equal to 'x'
        if ((top1.data + top2.data) == x):
             
            # Increment count
            count += 1
 
            # Pop nodes from the respective stacks
            st1.remove(st1[len(st1) - 1])
            st2.remove(st2[len(st2) - 1])
 
            # Insert next possible node in the
            # respective stacks
            root1 = top1.right
            root2 = top2.left
 
        # Move to next possible node in the
        # inorder traversal of BST 1
        elif ((top1.data + top2.data) < x):
            st1.remove(st1[len(st1) - 1])
            root1 = top1.right
 
        # Move to next possible node in the
        # reverse inorder traversal of BST 2
        else:
            st2.remove(st2[len(st2) - 1])
            root2 = top2.left
 
    # Required count of pairs
    return count
 
# Driver code
if __name__ == '__main__':
     
    # Formation of BST 1
    '''      5
           /   \ 
          3     7
         / \   / \
        2   4 6   8
    '''
    root1 = getNode(5) 
    root1.left = getNode(3)
    root1.right = getNode(7)
    root1.left.left = getNode(2)
    root1.left.right = getNode(4)
    root1.right.left = getNode(6)
    root1.right.right = getNode(8)
 
    # Formation of BST 2
    '''    10 
         /   \
        6     15
       / \   /  \ 
      3  8  11  18
    '''
    root2 = getNode(10)
    root2.left = getNode(6)
    root2.right = getNode(15)
    root2.left.left = getNode(3)
    root2.left.right = getNode(8)
    root2.right.left = getNode(11)
    root2.right.right = getNode(18)
 
    x = 16
     
    print("Pairs = ", countPairs(root1, root2, x))
 
# This code is contributed by bgangwar59

Time complexity: linear
Space complexity: logn
# Python program to find largest
# BST in a Binary Tree.
 
INT_MIN = -2147483648
INT_MAX = 2147483647
 
# Helper function that allocates a new
# node with the given data and None left
# and right pointers.
class newNode:
 
    # Constructor to create a new node
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
# Returns Information about subtree. The
# Information also includes size of largest
# subtree which is a BST
def largestBSTBT(root):
     
# Base cases : When tree is empty or it has
    # one child.
    if (root == None):
        return 0, INT_MIN, INT_MAX, 0, True
    if (root.left == None and root.right == None) :
        return 1, root.data, root.data, 1, True
 
    # Recur for left subtree and right subtrees
    l = largestBSTBT(root.left)
    r = largestBSTBT(root.right)
 
    # Create a return variable and initialize its
    # size.
    ret = [0, 0, 0, 0, 0]
    ret[0] = (1 + l[0] + r[0])
 
    # If whole tree rooted under current root is
    # BST.
    if (l[4] and r[4] and l[1] <
        root.data and r[2] > root.data) :
     
        ret[2] = min(l[2], root.data)
        ret[1] = max(r[1], root.data)
 
        # Update answer for tree rooted under
        # current 'root'
        ret[3] = max(l[3], r[3]) + 1;
        ret[4] = True
 
        return ret
     
 
    # If whole tree is not BST, return maximum
    # of left and right subtrees
    ret[3] = max(l[3], r[3])
    ret[4] = False
 
    return ret
 
# Driver Code
if __name__ == '__main__':
     
    """Let us construct the following Tree
        60
        / \
        65 70
    /
    50 """
    root = newNode(60)
    root.left = newNode(65)
    root.right = newNode(70)
    root.left.left = newNode(50)
    print("Size of the largest BST is",
                    largestBSTBT(root)[3])
                             
# This code is contributed
# Shubham Singh(SHUBHAMSINGH10)
# Naman Sharma (NAMANSHARMA1805)

Time complexity: linear
Space complexity: linear
# Python3 program to remove BST keys
# outside the given range
 
# A BST node has key, and left and right 
# pointers. A utility function to create
# a new BST node with key as given num
class newNode:
 
    # Constructor to create a new node
    def __init__(self, data):
        self.key = data
        self.left = None
        self.right = None
         
# Removes all nodes having value outside
# the given range and returns the root
# of modified tree
def removeOutsideRange(root, Min, Max):
     
    # Base Case
    if root == None:
        return None
     
    # First fix the left and right
    # subtrees of root
    root.left = removeOutsideRange(root.left,
                                   Min, Max)
    root.right = removeOutsideRange(root.right,
                                    Min, Max)
     
    # Now fix the root. There are 2
    # possible cases for root
    # 1.a) Root's key is smaller than
    #      min value (root is not in range)
    if root.key < Min:
        rChild = root.right
        return rChild
         
    # 1.b) Root's key is greater than max
    #      value (root is not in range)
    if root.key > Max:
        lChild = root.left
        return lChild
         
    # 2. Root is in range
    return root
 
 
# A utility function to insert a given
# key to BST
def insert(root, key):
    if root == None:
        return newNode(key)
    if root.key > key:
        root.left = insert(root.left, key)
    else:
        root.right = insert(root.right, key)
    return root
 
# Utility function to traverse the binary
# tree after conversion
def inorderTraversal(root):
    if root:
        inorderTraversal( root.left)
        print(root.key, end = " ")
        inorderTraversal( root.right)
 
# Driver Code
if __name__ == '__main__':
    root = None
    root = insert(root, 6)
    root = insert(root, -13)
    root = insert(root, 14)
    root = insert(root, -8)
    root = insert(root, 15)
    root = insert(root, 13)
    root = insert(root, 7)
 
    print("Inorder traversal of the given tree is:",
                                          end = " ")
    inorderTraversal(root)
 
    root = removeOutsideRange(root, -10, 13)
    print()
    print("Inorder traversal of the modified tree is:",
                                             end = " ")
    inorderTraversal(root)
 
# This code is contributed by PranchalK

Time complexity: linear
Space complexity: constant
# Python program to find BST keys in given range
 
# A binary tree node
class Node:
 
    # Constructor to create a new node
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
# The function prints all the keys in the given range
# [k1..k2]. Assumes that k1 < k2
def Print(root, k1, k2):
     
    # Base Case
    if root is None:
        return
 
    # Since the desired o/p is sorted, recurse for left
    # subtree first. If root.data is greater than k1, then
    # only we can get o/p keys in left subtree
    if k1 < root.data :
        Print(root.left, k1, k2)
 
    # If root's data lies in range, then prints root's data
    if k1 <= root.data and k2 >= root.data:
        print (root.data,end=' ')
 
    # recursively call the right subtree
    Print(root.right, k1, k2)
 
# Driver function to test above function
k1 = 10 ; k2 = 25 ;
root = Node(20)
root.left = Node(8)
root.right = Node(22)
root.left.left = Node(4)
root.left.right = Node(12)
 
Print(root, k1, k2)
 
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)

Time complexity: linear
Space complexity: logn
# Python3 code to print BST keys in given Range
# in constant space using Morris traversal.
 
# Helper function to create a new node
class newNode:
 
    # Constructor to create a new node
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
# Function to print the keys in range
def RangeTraversal(root, n1, n2):
    if root == None:
        return
 
    curr = root
    while curr:
        if curr.left == None:
             
            # check if current node lies
            # between n1 and n2
            if curr.data <= n2 and curr.data >= n1:
                print(curr.data, end = " ")
            curr = curr.right
        else:
            pre = curr.left
             
            # finding the inorder predecessor-
            # inorder predecessor is the right
            # most in left subtree or the left
            # child, i.e in BST it is the
            # maximum(right most) in left subtree.
            while (pre.right != None and
                   pre.right != curr):
                pre = pre.right
                         
            if pre.right == None:
                pre.right = curr;
                curr = curr.left
            else:
                pre.right = None
 
                # check if current node lies
                # between n1 and n2
                if curr.data <= n2 and curr.data >= n1:
                    print(curr.data, end = " ")
                curr = curr.right
 
# Driver Code
if __name__ == '__main__':
 
    # Constructed binary tree is
    #        4
    #      / \
    #     2      7
    #    / \ / \
    #   1  3 6 10
    root = newNode(4)
    root.left = newNode(2)
    root.right = newNode(7)
    root.left.left = newNode(1)
    root.left.right = newNode(3)
    root.right.left = newNode(6)
    root.right.right = newNode(10)
 
    RangeTraversal(root, 4, 12)    
     
# This code is contributed by PranchalK

Time complexity: linear
Space complexity: constant
# Python3 program to count BST nodes
# within a given range
 
# Utility function to create new node
class newNode:
 
    # Constructor to create a new node
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
# Returns count of nodes in BST in
# range [low, high]
def getCount(root, low, high):
     
    # Base case
    if root == None:
        return 0
         
    # Special Optional case for improving
    # efficiency
    if root.data == high and root.data == low:
        return 1
 
    # If current node is in range, then
    # include it in count and recur for
    # left and right children of it
    if root.data <= high and root.data >= low:
        return (1 + getCount(root.left, low, high) +
                    getCount(root.right, low, high))
 
    # If current node is smaller than low,
    # then recur for right child
    elif root.data < low:
        return getCount(root.right, low, high)
 
    # Else recur for left child
    else:
        return getCount(root.left, low, high)
 
# Driver Code
if __name__ == '__main__':
     
    # Let us construct the BST shown in
    # the above figure
    root = newNode(10)
    root.left = newNode(5)
    root.right = newNode(50)
    root.left.left = newNode(1)
    root.right.left = newNode(40)
    root.right.right = newNode(100)
     
    # Let us constructed BST shown in above example
    #     10
    #     / \
    # 5     50
    # /     / \
    # 1     40 100
    l = 5
    h = 45
    print("Count of nodes between [", l, ", ", h,"] is ",
                                    getCount(root, l, h))
 
# This code is contributed by PranchalK

Time complexity: constant
Space complexity: linear
# Python3 program to find Sum Of All
# Elements smaller than or equal to
# Kth Smallest Element In BST
 
INT_MAX = 2147483647
 
# Binary Tree Node
""" utility that allocates a newNode
with the given key """
class createNode:
 
    # Construct to create a newNode
    def __init__(self, key):
        self.data = key
        self.left = None
        self.right = None
 
# A utility function to insert a new
# Node with given key in BST and also
# maintain lcount ,Sum
def insert(root, key) :
 
    # If the tree is empty, return a new Node
    if (root == None) :
        return createNode(key)
 
    # Otherwise, recur down the tree
    if (root.data > key) :
        root.left = insert(root.left, key)
 
    else if (root.data < key):
        root.right = insert(root.right, key)
 
    # return the (unchanged) Node pointer
    return root
 
# function return sum of all element smaller
# than and equal to Kth smallest element
def ksmallestElementSumRec(root, k, count) :
 
    # Base cases
    if (root == None) :
        return 0
    if (count[0] > k[0]) :
        return 0
 
    # Compute sum of elements in left subtree
    res = ksmallestElementSumRec(root.left, k, count)
    if (count[0] >= k[0]) :
        return res
 
    # Add root's data
    res += root.data
 
    # Add current Node
    count[0] += 1
    if (count[0] >= k[0]) :
        return res
 
    # If count is less than k, return
    # right subtree Nodes
    return res + ksmallestElementSumRec(root.right,
                                        k, count)
 
# Wrapper over ksmallestElementSumRec()
def ksmallestElementSum(root, k):
    count = [0]
    return ksmallestElementSumRec(root, k, count)
 
# Driver Code
if __name__ == '__main__':
 
    """ 20
        / \
    8 22
    / \
    4 12
        / \
        10 14
        """
    root = None
    root = insert(root, 20)
    root = insert(root, 8)
    root = insert(root, 4)
    root = insert(root, 12)
    root = insert(root, 10)
    root = insert(root, 14)
    root = insert(root, 22)
     
    k = [3]
    print(ksmallestElementSum(root, k))
 
# This code is contributed by
# Shubham Singh(SHUBHAMSINGH10)

Time complexity: constant
Space complexity: logn
# Python3 program to find predecessor
# and successor in a BST
 
# A utility function to create a
# new BST node
class newNode:
     
    # Constructor to create a new node
    def __init__(self, data):
        self.key = data
        self.left = None
        self.right = None
         
# Function that finds predecessor and
# successor of key in BST.
def findPreSuc(root, pre, suc, key):
    if root == None:
        return
 
    # Search for given key in BST.
    while root != None:
 
        # If root is given key.
        if root.key == key:
 
            # the minimum value in right
            # subtree is predecessor.
            if root.right:
                suc[0] = root.right
                while suc[0].left:
                    suc[0] = suc[0].left
 
            # the maximum value in left
            # subtree is successor.
            if root.left:
                pre[0] = root.left
                while pre[0].right:
                    pre[0] = pre[0].right
 
            return
 
        # If key is greater than root, then
        # key lies in right subtree. Root
        # could be predecessor if left
        # subtree of key is null.
        elif root.key < key:
            pre[0] = root
            root = root.right
 
        # If key is smaller than root, then
        # key lies in left subtree. Root
        # could be successor if right
        # subtree of key is null.
        else:
            suc[0] = root
            root = root.left
 
# A utility function to insert
# a new node with given key in BST
def insert(node, key):
    if node == None:
        return newNode(key)
    if key < node.key:
        node.left = insert(node.left, key)
    else:
        node.right = insert(node.right, key)
    return node
 
# Driver Code
if __name__ == '__main__':
    key = 65 # Key to be searched in BST
 
    # Let us create following BST
    #             50
    #         / \
    #         / \
    #         30     70
    #         / \     / \
    #     / \ / \
    #     20 40 60 80
 
    root = None
    root = insert(root, 50)
    insert(root, 30)
    insert(root, 20)
    insert(root, 40)
    insert(root, 70)
    insert(root, 60)
    insert(root, 80)
 
    pre, suc = [None], [None]
 
    findPreSuc(root, pre, suc, key)
    if pre[0] != None:
        print("Predecessor is", pre[0].key)
    else:
        print("-1")
 
    if suc[0] != None:
        print("Successor is", suc[0].key)
    else:
        print("-1")
 
# This code is contributed by PranchalK

Time complexity: linear
Space complexity: constant
# Python3 program to find a pair with
# given sum using hashing
import sys
import math
 
 
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
 
def insert(root, data):
    if root is None:
        return Node(data)
    if(data < root.data):
        root.left = insert(root.left, data)
    if(data > root.data):
        root.right = insert(root.right, data)
    return root
 
 
def findPairUtil(root, summ, unsorted_set):
    if root is None:
        return False
    if findPairUtil(root.left, summ, unsorted_set):
        return True
    if unsorted_set and (summ-root.data) in unsorted_set:
        print("Pair is Found ({},{})".format(summ-root.data, root.data))
        return True
    else:
        unsorted_set.add(root.data)
 
    return findPairUtil(root.right, summ, unsorted_set)
 
 
def findPair(root, summ):
    unsorted_set = set()
    if(not findPairUtil(root, summ, unsorted_set)):
        print("Pair do not exist!")
 
 
# Driver code
if __name__ == '__main__':
    root = None
    root = insert(root, 15)
    root = insert(root, 10)
    root = insert(root, 20)
    root = insert(root, 8)
    root = insert(root, 12)
    root = insert(root, 16)
    root = insert(root, 25)
    root = insert(root, 10)
    summ = 28
    findPair(root, summ)
 
# This code is contributed by Vikash Kumar 37

Time complexity: linear
Space complexity: linear