Skip to content

Commit ef2859b

Browse files
committed
updates
1 parent b45d4d8 commit ef2859b

4 files changed

Lines changed: 374 additions & 0 deletions

File tree

‎DailyByte/Trees/ConvertBSTtoLL.py‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""
2+
Problem:
3+
-----------------------------------------------
4+
https://leetcode.com/problems/increasing-order-search-tree/
5+
6+
Given a binary search tree, rearrange the tree
7+
such that it forms a linked list where all its values are in ascending order.
8+
Ex: Given the following tree...
9+
5
10+
/ \
11+
1 6
12+
return...
13+
1
14+
\
15+
5
16+
\
17+
6
18+
Ex: Given the following tree...
19+
5
20+
/ \
21+
2 9
22+
/ \
23+
1 3
24+
return...
25+
1
26+
\
27+
2
28+
\
29+
3
30+
\
31+
5
32+
\
33+
9
34+
Ex: Given the following tree...
35+
5
36+
\
37+
6
38+
return...
39+
5
40+
\
41+
6
42+
43+
44+
Increasing BST (In-Order Traversal) Solution:
45+
-----------------------------------------------
46+
A simple approach will be to recreate the BST from its in-order traversal.
47+
This will take O(N) extra space where N is the number of nodes in BST.
48+
Re-draw the entire tree such that left part of each node takes None.
49+
50+
@complexity:
51+
Time: O(n), where n is the number of nodes in the tree
52+
Space: O(h), where h is the height of the tree and the size of the implicit call stack in our in-order traversal
53+
"""
54+
55+
56+
class BST:
57+
def __init__(self, value, right=None, left=None):
58+
self.value = value
59+
self.right = right
60+
self.left = left
61+
62+
63+
class Solution:
64+
def convert(self):
65+
pass
66+
67+
def increasingBST(self, root, tail=None):
68+
if not root:
69+
return tail
70+
71+
res = self.increasingBST(root.left, root)
72+
73+
root.left = None
74+
75+
root.right = self.increasingBST(root.right, tail)
76+
77+
return res
78+
79+
80+
class Tests:
81+
82+
def __init__(self):
83+
root = BST(5)
84+
root.left = BST(1)
85+
root.right = BST(6)
86+
87+
root = BST(5)
88+
root.left = BST(2)
89+
root.right = BST(9)
90+
root.left.left = BST(1)
91+
root.left.right = BST(3)
92+
93+
s = Solution()
94+
95+
def printList(parent):
96+
curr = parent
97+
while curr is not None:
98+
print(curr.value, end=' ')
99+
curr = curr.right
100+
101+
printList(s.increasingBST(root))
102+
103+
104+
t = Tests()

‎DailyByte/Trees/FindValue.py‎

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"""
2+
Problem:
3+
-----------------------------------------------
4+
This question is asked by Google. Given the reference to the root of a binary search tree and a search value,
5+
return the reference to the node that contains the value if it exists and null otherwise.
6+
Note: all values in the binary search tree will be unique.
7+
Ex: Given the tree...
8+
3
9+
/ \
10+
1 4
11+
and the search value 1 return a reference to the node containing 1.
12+
Ex: Given the tree
13+
7
14+
/ \
15+
5 9
16+
/ \
17+
8 10
18+
and the search value 9 return a reference to the node containing 9.
19+
Ex: Given the tree
20+
8
21+
/ \
22+
6 9
23+
and the search value 7 return null.
24+
25+
26+
Traversing Solution:
27+
-----------------------------------------------
28+
@description:
29+
Recursively pass through the BST,
30+
at each step we choose the subtree we need to go on with.
31+
The exit loop is a null node.
32+
If the current value is smaller => go to the right subtree
33+
If the current value is bigger => go to the left subtree
34+
Return root
35+
36+
@complexity:
37+
Time: O(n) | can be O(log n) if balanced, where n is the number of nodes in the tree
38+
Space: O(n) | can be O(h) if balanced, where h is the height of the tree
39+
"""
40+
41+
42+
class BST:
43+
def __init__(self, value, right=None, left=None):
44+
self.value = value
45+
self.right = right
46+
self.left = left
47+
48+
49+
class Solution:
50+
def findValue(self, root, value):
51+
if root is None:
52+
return None
53+
54+
if value > root.value:
55+
return self.findValue(root.right, value)
56+
elif value < root.value:
57+
return self.findValue(root.left, value)
58+
59+
return root
60+
61+
62+
# 3
63+
# / \
64+
# 1 4
65+
66+
bst = BST(3)
67+
bst.left = BST(1)
68+
bst.right = BST(4)
69+
70+
s = Solution()
71+
72+
assert (s.findValue(bst, 1).value) == 1
73+
74+
# 7
75+
# / \
76+
# 5 9
77+
# / \
78+
# 8 10
79+
80+
bst = BST(7)
81+
bst.left = BST(5)
82+
bst.right = BST(9)
83+
bst.right.left = BST(8)
84+
bst.right.right = BST(10)
85+
86+
assert (s.findValue(bst, 9).value) == 9
87+
88+
89+
# 8
90+
# / \
91+
# 6 9
92+
93+
bst = BST(8)
94+
bst.left = BST(6)
95+
bst.right = BST(9)
96+
97+
assert (s.findValue(bst, 7)) is None

‎DailyByte/Trees/LCAofBST.py‎

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"""
2+
Problem:
3+
-----------------------------------------------
4+
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
5+
6+
Given a binary search tree that contains unique values and two nodes within the tree, a, and b,
7+
return their lowest common ancestor.
8+
Note: the lowest common ancestor of two nodes is
9+
the deepest node within the tree such that both nodes are descendants of it.
10+
Ex: Given the following tree...
11+
7
12+
/ \
13+
2 9
14+
/ \
15+
1 5
16+
and a = 1, b = 9, return a reference to the node containing 7.
17+
Ex: Given the following tree...
18+
8
19+
/ \
20+
3 9
21+
/ \
22+
2 6
23+
and a = 2, b = 6, return a reference to the node containing 3.
24+
Ex: Given the following tree...
25+
8
26+
/ \
27+
6 9
28+
and a = 6, b = 8, return a reference to the node containing 8.
29+
30+
31+
Naive Solution:
32+
-----------------------------------------------
33+
@description:
34+
A simple solution would be to store the path from root to x
35+
and the path from the root to y in two auxiliary arrays.
36+
Then traverse both arrays simultaneously till the values in the arrays match.
37+
The last matched value will be the LCA.
38+
If the end of one array is reached, then the last seen value is LCA.
39+
Either p or q is the root => return root
40+
41+
@complexity:
42+
Time: O(n), for a binary search tree with n nodes
43+
Space: O(n), for storing two arrays
44+
45+
46+
Solution:
47+
-----------------------------------------------
48+
@description:
49+
We can recursively find the lowest common ancestor of nodes x and y present in the BST.
50+
The trick is to find the BST node,
51+
which has one key present in its left subtree and the other key present in the right subtree.
52+
If any such node is present in the tree, then it is LCA
53+
If y lies in the subtree rooted at node x, then x is the LCA
54+
Otherwise, if x lies in the subtree rooted at node y, then y is the LCA
55+
56+
@complexity:
57+
Recursive:
58+
Time: O(n), for a binary search tree with n nodes
59+
Space: O(h), it requires space proportional to the tree’s height for the call stack
60+
Iterative:
61+
Time: O(n), for a binary search tree with n nodes
62+
Space: O(1), no auxiliary space required
63+
"""
64+
65+
66+
class Node:
67+
def __init__(self, key=0, left=None, right=None):
68+
self.key = key
69+
self.left = left
70+
self.right = right
71+
72+
73+
class Solution:
74+
def LCArecursive(self, root, p, q):
75+
# Base case: empty tree
76+
if root is None:
77+
return None
78+
79+
# If both p and q are smaller than the root, LCA exists in the left subtree
80+
if root.key > max(p.key, q.key):
81+
return self.LCArecursive(root.left, p, q)
82+
83+
# If both p and q are greater than the root, LCA exists in the right subtree
84+
elif root.key < min(p.key, q.key):
85+
return self.LCArecursive(root.right, p, q)
86+
87+
# If one key is greater (or equal) to the root
88+
# and one key is smaller (or equal) than the root
89+
# then the current node is LCA
90+
return root
91+
92+
def LCAiterative(self, root, p, q):
93+
if root is None:
94+
return None
95+
96+
curr = root
97+
98+
while curr:
99+
if curr.key > max(p.key, q.key):
100+
curr = curr.left
101+
elif curr.key < min(p.key, q.key):
102+
curr = curr.right
103+
else:
104+
return curr
105+
106+
return curr

‎DailyByte/Trees/LCAofBT.py‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""
2+
Problem:
3+
-----------------------------------------------
4+
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/
5+
6+
7+
Solution:
8+
-----------------------------------------------
9+
@description:
10+
Recursive solution
11+
If the current (sub)tree contains both p and q, then the function result is their LCA.
12+
If only one of them is in that subtree, then the result is that one of them.
13+
If neither are in that subtree, the result is null/None/nil.
14+
15+
Iterative solution
16+
I do a post-order traversal with a stack.
17+
Each stack element at first is a [node, parent] pair,
18+
where parent is the stack element of the node's parent node.
19+
When the children of a parent get finished,
20+
their results are appended to their parent's stack element.
21+
So when a parent gets finished, we have the results of its children/subtrees available
22+
(its stack element at that point is [node, parent, resultForLeftSubtree, resultForRightSubtree]).
23+
24+
@complexity:
25+
Time: O(n), where n is the number of nodes in the BT
26+
Space: O(n), for the recursive call stack
27+
O(n), for the stack
28+
"""
29+
30+
31+
class Node:
32+
def __init__(self, key=0, left=None, right=None):
33+
self.key = key
34+
self.left = left
35+
self.right = right
36+
37+
38+
class Solution(object):
39+
def lowestCommonAncestor(self, root, p, q):
40+
if root is None:
41+
return None
42+
43+
if root == p or root == q:
44+
return root
45+
46+
left_res = self.lowestCommonAncestor(root.left, p, q)
47+
right_res = self.lowestCommonAncestor(root.right, p, q)
48+
49+
# If looking for me, return myself
50+
if (left_res and right_res) or (root in [p, q]):
51+
return root
52+
else:
53+
return left_res or right_res
54+
55+
def lowestCommonAncestorIterative(self, root, p, q):
56+
answer = []
57+
stack = [[root, answer]]
58+
while stack:
59+
top = stack.pop()
60+
(node, parent), subs = top[:2], top[2:]
61+
if node in (None, p, q):
62+
parent += node,
63+
elif not subs:
64+
stack += top, [node.right, top], [node.left, top]
65+
else:
66+
parent += node if all(subs) else max(subs),
67+
return answer[0]

0 commit comments

Comments
 (0)