Skip to content

Commit 8c11b0d

Browse files
author
Chris Wu
committed
no message
1 parent cda3f41 commit 8c11b0d

3 files changed

+170
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class Solution(object):
2+
def sortedArrayToBST(self, nums):
3+
if not nums: return None
4+
5+
m = len(nums)/2
6+
root = TreeNode(nums[m], self.sortedArrayToBST(nums[:m]), self.sortedArrayToBST(nums[m+1:]))
7+
return root
8+
9+
10+
"""
11+
`nums` is a sorted array.
12+
To construct the most balanced BST, we must use the median number in `nums` as root.
13+
So the number of elements under left subtree and right subtree will be the same.
14+
15+
Now we know which element in the `nums` will be root.
16+
For `root.left` we only need to consider `nums[:m]`.
17+
For `root.right` we only need to consider `nums[m+1:]`.
18+
Which needs to be a balanced BST, too. So we apply the same logic.
19+
20+
Time: O(N). Because there will be N element being construct.
21+
Space: O(LogN). There will be LogN level of recursive call.
22+
"""

problems/delete-node-in-a-bst.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
class Solution(object):
2+
def deleteNode(self, root, key):
3+
def find_min(root):
4+
curr = root
5+
while curr.left: curr = curr.left
6+
return curr.val#[5]
7+
8+
def remove(node):
9+
if node.left and node.right:
10+
node.val = find_min(node.right)
11+
node.right = self.deleteNode(node.right, node.val)
12+
return node #[4]
13+
elif node.left and not node.right:
14+
return node.left #[3]
15+
elif node.right and not node.left:
16+
return node.right #[3]
17+
else:
18+
return None #[2]
19+
20+
if not root: return root
21+
node = root
22+
23+
while node: #[0]
24+
if node.val==key:
25+
return remove(node) #[1]
26+
elif node.left and node.left.val==key:
27+
node.left = remove(node.left) #[1]
28+
return root
29+
elif node.right and node.right.val==key:
30+
node.right = remove(node.right) #[1]
31+
return root
32+
33+
if key>node.val and node.right:
34+
node = node.right
35+
elif key<node.val and node.left:
36+
node = node.left
37+
else:
38+
break
39+
40+
return root
41+
42+
"""
43+
Find the parant and the node to be deleted. [0]
44+
Deleting the node means replacing its reference by something else. [1]
45+
46+
For the node to be deleted, if it only has no child, just remove it from the parent. Return None. [2]
47+
48+
If it has one child, return the child. So its parent will directly connect to its child. [3]
49+
50+
If it has both child. Update the node's val to the minimum value in the right subtree. Remove the minimum value node in the right subtree. [4]
51+
This is equivalent to replacing the node by the minimum value node in the right subtree.
52+
Another option is to replace the node by the maximum value node in the left subtree.
53+
54+
Find the minimum value in the left subtree is easy. The leftest node value in the tree is the smallest. [5]
55+
56+
Time Complexity: O(LogN). O(LogN) for finding the node to be deleted.
57+
The recursive call in `remove()` will be apply to a much smaller subtree. And much smaller subtree...
58+
So can be ignored.
59+
Space complexity is O(LogN). Because the recursive call will at most be called LogN times.
60+
N is the number of nodes. And LogN can be consider the height of the tree.
61+
"""
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from collections import Counter
2+
class Solution(object):
3+
def findMode(self, root):
4+
def count(node):
5+
counter[node.val] += 1
6+
if node.left: count(node.left)
7+
if node.right: count(node.right)
8+
9+
if not root: return []
10+
11+
counter = Counter()
12+
count(root)
13+
max_count = max(counter.values())
14+
return [val for val, count in counter.items() if count==max_count]
15+
16+
"""
17+
Time: O(N). For we traverse every node recursively.
18+
Space: O(N). Becuase we store all element's val and count in `counter`.
19+
Note that, we do not use the feature of BST.
20+
"""
21+
22+
class Solution(object):
23+
def findMode(self, root):
24+
if not root: return []
25+
26+
ans = []
27+
stack = []
28+
prev_val = None
29+
curr = root
30+
curr_count = 0
31+
max_count = float('-inf')
32+
33+
while curr or stack:
34+
while curr:
35+
stack.append(curr)
36+
curr = curr.left
37+
curr = stack.pop()
38+
39+
#[0]
40+
if curr.val!=prev_val:
41+
curr_count = 1
42+
prev_val = curr.val
43+
else:
44+
curr_count += 1
45+
46+
#[1]
47+
if curr_count>max_count:
48+
ans = [curr.val]
49+
max_count = curr_count
50+
elif curr_count==max_count:
51+
ans.append(curr.val)
52+
53+
curr = curr.right
54+
55+
return ans
56+
57+
"""
58+
To use the feature of BST, we are going to inorder traverse the BST.
59+
So it will be like we are iterating a sorted array.
60+
61+
[1]
62+
While iterating, we can put only the element count that is greater or equal than `max_count` to `ans`.
63+
If we encounter a new element with larger `curr_count`, we reset the `ans`.
64+
65+
[0]
66+
With the help of `prev_val` we can know that `curr_node` is the same to the previous or not.
67+
If not, its a new element, we need to reset the `curr_count`.
68+
69+
Time: O(N). Space: O(1)
70+
71+
For better understanding, below is a template for inorder traverse.
72+
"""
73+
74+
#inorder traversal of BST
75+
def inorder_traverse(root):
76+
curr = root
77+
stack = []
78+
while curr or stack:
79+
while curr:
80+
stack.append(curr)
81+
curr = curr.left
82+
curr = stack.pop()
83+
84+
#do something to the current node
85+
print curr.val
86+
87+
curr = curr.right

0 commit comments

Comments
 (0)