diff --git a/Problem1.py b/Problem1.py new file mode 100644 index 00000000..8d9d26b2 --- /dev/null +++ b/Problem1.py @@ -0,0 +1,59 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + +# Time Complexity --> O(n) where n is the number of nodes in the tree +# Space Complexity --> O(log n) which is the height of the tree +# Approach --> Have a previous val that keeps updating as we make inorder recursive calls and compare it with current root val. +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + self.flag = True + self.prev = None + self.helper(root) + return self.flag + + def helper(self, root): + # base + if root is None: + return + + # logic + self.helper(root.left) + if self.prev is not None and self.prev.val>=root.val: + self.flag = False + + self.prev = root + if self.flag: + self.helper(root.right) + + + +''' +# Time Complexity --> O(n) where n is the number of nodes in the tree +# Space Complexity --> O(log n) which is the height of the tree +# Approach --> range-based recursion where we pass the min and max values as parameters for each function call and make boundary checks for the root value +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + return self.helper(root, None, None) + + def helper(self, root, min_val, max_val): + # base + if root is None: + return True + + # logic + left = self.helper(root.left, min_val, root.val) + + if min_val is not None and root.val<=min_val: + return False + if max_val is not None and root.val>=max_val: + return False + + if left: + right = self.helper(root.right, root.val, max_val) + + return left and right +''' diff --git a/Problem2.py b/Problem2.py new file mode 100644 index 00000000..2f6d322b --- /dev/null +++ b/Problem2.py @@ -0,0 +1,58 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + +# Time Complexity --> O(n) +# Space Complexity --> O(n) +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + n = len(preorder) + self.idx = 0 + hmap = {} + for i in range(len(inorder)): + hmap[inorder[i]] = i + return self.helper(preorder, 0, n-1, hmap) + + def helper(self, preorder, st, end, hmap): + # base + if st>end: + return None + # logic + root_val = preorder[self.idx] + self.idx += 1 + root_idx = hmap[root_val] + root = TreeNode(root_val) + + root.left = self.helper(preorder, st, root_idx-1, hmap) + root.right = self.helper(preorder, root_idx+1, end, hmap) + + return root + +''' +# Time Complexity --> O(n^2) +# Space Complexity --> O(n^2) +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + if len(preorder)==0: + return None + root_val = preorder[0] + hmap = {} + for i in range(len(inorder)): + hmap[inorder[i]] = i + + root_idx = hmap[root_val] + + inleft = inorder[:root_idx] + inright = inorder[root_idx+1:] + preleft = preorder[1:len(inleft)+1] + preright = preorder[len(inleft)+1:] + + root = TreeNode(root_val) + root.left = self.buildTree(preleft, inleft) + root.right = self.buildTree(preright, inright) + + return root +'''