Skip to content

Commit 88f17e0

Browse files
committed
LeetCode 701. Insert into a Binary Search Tree
1 parent 9288a63 commit 88f17e0

14 files changed

+238
-14
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ Solutions to LeetCode problems. The first column links to the problem in LeetCod
265265
| [684. Redundant Connection][lc684] | 🟠 Medium | [![python](res/py.png)][lc684py] |
266266
| [692. Top K Frequent Words][lc692] | 🟠 Medium | [![python](res/py.png)][lc692py] |
267267
| [695. Max Area of Island][lc695] | 🟠 Medium | [![python](res/py.png)][lc695py] |
268+
| [701. Insert into a Binary Search Tree][lc701] | 🟠 Medium | [![python](res/py.png)][lc701py] [![rust](res/rs.png)][lc701rs] |
268269
| [703. Kth Largest Element in a Stream][lc703] | 🟢 Easy | [![python](res/py.png)][lc703py] |
269270
| [704. Binary Search][lc704] | 🟢 Easy | [![python](res/py.png)][lc704py] |
270271
| [718. Maximum Length of Repeated Subarray][lc718] | 🟠 Medium | [![python](res/py.png)][lc718py] |
@@ -939,6 +940,9 @@ Solutions to LeetCode problems. The first column links to the problem in LeetCod
939940
[lc692py]: leetcode/top-k-frequent-words.py
940941
[lc695]: https://leetcode.com/problems/max-area-of-island/
941942
[lc695py]: leetcode/max-area-of-island.py
943+
[lc701]: https://leetcode.com/problems/insert-into-a-binary-search-tree/
944+
[lc701py]: leetcode/insert-into-a-binary-search-tree.py
945+
[lc701rs]: leetcode/insert-into-a-binary-search-tree.rs
942946
[lc703]: https://leetcode.com/problems/kth-largest-element-in-a-stream/
943947
[lc703py]: leetcode/kth-largest-element-in-a-stream.py
944948
[lc704]: https://leetcode.com/problems/binary-search/

algoexpert/max-profit-with-k-transactions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
# The max profit each day depends on the max profit the previous day,
13-
# wether we are holding stock or not, and the number of transactions
13+
# whether we are holding stock or not, and the number of transactions
1414
# that we have left.
1515
#
1616
# Time complexity: O(k*n) - The outer loop iterates over n positions

leetcode/bag-of-tokens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def bagOfTokensScore(self, tokens: List[int], power: int) -> int:
2626
# We want to access both the smallest and biggest element,
2727
# sort the tokens and use a deque to store them.
2828
q = deque(sorted(tokens))
29-
# Keep track of the length of the queue to determine wether we
29+
# Keep track of the length of the queue to determine whether we
3030
# made a move on the last round.
3131
last_token_count = len(q) + 1
3232
# Keep going while we have tokens and we made a move on the last

leetcode/binary-tree-pruning.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
2828
# Base case.
2929
if not root:
3030
return None
31-
# DFS function returns wether the child contains a 1.
31+
# DFS function returns whether the child contains a 1.
3232
def containsOne(node: TreeNode) -> bool:
3333
# Unlink the children if they exist and do not contain a 1.
3434
if node.left and not containsOne(node.left):

leetcode/determine-if-string-halves-are-alike.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
import timeit
99

10-
# Count the number of vowels in each half of the string, return wether
10+
11+
# Count the number of vowels in each half of the string, return whether
1112
# the count is the same.
1213
#
1314
# Time complexity: O(n) - We visit all elements in the input and perform

leetcode/find-and-replace-pattern.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def findAndReplacePattern(
4747

4848
# Mapping of the current word's characters to the pattern
4949
wd = {}
50-
# Flag wether the character matches.
50+
# Flag whether the character matches.
5151
match = True
5252
# Visit each character in word matching its characters with
5353
# its index the first time we see it. Then check if the
@@ -99,7 +99,7 @@ def match(word):
9999
# Use dictionaries and setdefault to match the characters in
100100
# the word to the ones in the pattern.
101101
wd, pd = {}, {}
102-
# Return wether each character of word could be substituted
102+
# Return whether each character of word could be substituted
103103
# with the corresponding character in pattern to give the
104104
# same result.
105105
return all(

leetcode/flip-string-to-monotone-increasing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def minFlipsMonoIncr(self, s: str) -> int:
6666
# We can append a 1 to the right at no extra cost.
6767
ones += 1
6868
else:
69-
# We need to decide wether it is better to flip this 0
69+
# We need to decide whether it is better to flip this 0
7070
# to a 1 or would have been better to flip all 1s in the
7171
# prefix to a 0.
7272
# res = min(ones, res + 1)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# 701. Insert into a Binary Search Tree
2+
# 🟠 Medium
3+
#
4+
# https://leetcode.com/problems/insert-into-a-binary-search-tree/
5+
#
6+
# Tags: Tree - Binary Search Tree - Binary Tree
7+
8+
import timeit
9+
from typing import Optional
10+
11+
from utils.binary_tree import BinaryTree, TreeNode
12+
13+
14+
# Travel through the tree choosing to go right or left based on node
15+
# values until we find the leave below which we will need to insert
16+
# the new node.
17+
#
18+
# Time Complexity: Best: O(log(n)) Worst: O(n) - We will travel the
19+
# entire height of the tree, ideally, it would be a well balanced tree
20+
# and its height would be log(n), but a skewed tree could have a height
21+
# of n, since we are not doing any balancing, after multiple inserts,
22+
# depending on the order in which the values were inserted, the tree
23+
# could become skewed.
24+
# Space complexity: Best: O(log(n)) Worst: O(n) - Each node that we
25+
# visit will add one call to the call stack, we could improve it to O(1)
26+
# using an iterative method because we only need to keep a pointer to
27+
# one node.
28+
#
29+
# Runtime 136 ms Beats 73.62%
30+
# Memory 16.9 MB Beats 90.27%
31+
class Solution:
32+
def insertIntoBST(
33+
self, root: Optional[TreeNode], val: int
34+
) -> Optional[TreeNode]:
35+
node = TreeNode(val)
36+
if not root:
37+
return node
38+
39+
def ins(child, parent) -> None:
40+
if child.val < parent.val:
41+
if parent.left:
42+
ins(child, parent.left)
43+
else:
44+
parent.left = child
45+
else:
46+
if parent.right:
47+
ins(child, parent.right)
48+
else:
49+
parent.right = child
50+
51+
ins(node, root)
52+
return root
53+
54+
55+
def test():
56+
executors = [Solution]
57+
tests = [
58+
[[4, 2, 7, 1, 3], 5, [1, 2, 3, 4, 5, 7]],
59+
[[40, 20, 60, 10, 30, 50, 70], 25, [10, 20, 25, 30, 40, 50, 60, 70]],
60+
[
61+
[4, 2, 7, 1, 3, None, None, None, None, None, None],
62+
5,
63+
[1, 2, 3, 4, 5, 7],
64+
],
65+
]
66+
for executor in executors:
67+
start = timeit.default_timer()
68+
for _ in range(1):
69+
for col, t in enumerate(tests):
70+
sol = executor()
71+
root = BinaryTree.fromList(t[0]).getRoot()
72+
result_root = sol.insertIntoBST(root, t[1])
73+
result = BinaryTree(result_root).inOrderTraverse()
74+
exp = t[2]
75+
assert result == exp, (
76+
f"\033[93m» {result} <> {exp}\033[91m for"
77+
+ f" test {col} using \033[1m{executor.__name__}"
78+
)
79+
stop = timeit.default_timer()
80+
used = str(round(stop - start, 5))
81+
cols = "{0:20}{1:10}{2:10}"
82+
res = cols.format(executor.__name__, used, "seconds")
83+
print(f"\033[92m» {res}\033[0m")
84+
85+
86+
test()
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// 701. Insert into a Binary Search Tree
2+
// 🟠 Medium
3+
//
4+
// https://leetcode.com/problems/insert-into-a-binary-search-tree/
5+
//
6+
// Tags: Tree - Binary Search Tree - Binary Tree
7+
8+
use std::cell::RefCell;
9+
use std::rc::Rc;
10+
11+
struct Solution;
12+
impl Solution {
13+
// Travel through the tree choosing to go right or left based on node
14+
// values until we find the leave below which we will need to insert
15+
// the new node.
16+
//
17+
// Time Complexity: Best: O(log(n)) Worst: O(n) - We will travel the
18+
// entire height of the tree, ideally, it would be a well balanced tree
19+
// and its height would be log(n), but a skewed tree could have a height
20+
// of n, since we are not doing any balancing, after multiple inserts,
21+
// depending on the order in which the values were inserted, the tree
22+
// could become skewed.
23+
// Space complexity: O(1) - We only store a reference to the root and to
24+
// the current node that we are visiting.
25+
//
26+
// Runtime 12 ms Beats 72.73%
27+
// Memory 2.6 MB Beats 72.73%
28+
pub fn insert_into_bst(
29+
root: Option<Rc<RefCell<TreeNode>>>,
30+
val: i32,
31+
) -> Option<Rc<RefCell<TreeNode>>> {
32+
let new_node = TreeNode {
33+
val,
34+
left: None,
35+
right: None,
36+
};
37+
if root.is_none() {
38+
return Some(Rc::new(RefCell::new(new_node)));
39+
}
40+
let mut n = root.clone();
41+
loop {
42+
match n {
43+
Some(node) => {
44+
if val < node.borrow().val {
45+
if node.borrow().left.is_some() {
46+
n = node.borrow().left.clone();
47+
} else {
48+
node.borrow_mut().left = Some(Rc::new(RefCell::new(new_node)));
49+
break;
50+
}
51+
} else {
52+
if node.borrow().right.is_some() {
53+
n = node.borrow().right.clone();
54+
} else {
55+
node.borrow_mut().right = Some(Rc::new(RefCell::new(new_node)));
56+
break;
57+
}
58+
}
59+
}
60+
None => panic!("This code should never run"),
61+
}
62+
}
63+
root
64+
}
65+
66+
// Travel through the tree choosing to go right or left based on node
67+
// values until we find the leave below which we will need to insert
68+
// the new node.
69+
//
70+
// Time Complexity: Best: O(log(n)) Worst: O(n) - We will travel the
71+
// entire height of the tree, ideally, it would be a well balanced tree
72+
// and its height would be log(n), but a skewed tree could have a height
73+
// of n, since we are not doing any balancing, after multiple inserts,
74+
// depending on the order in which the values were inserted, the tree
75+
// could become skewed.
76+
// Space complexity: Best: O(log(n)) Worst: O(n) - Each node that we
77+
// visit will add one call to the call stack.
78+
//
79+
// Runtime 8 ms Beats 90.91%
80+
// Memory 2.6 MB Beats 72.73%
81+
pub fn insert_into_bst_rec(
82+
root: Option<Rc<RefCell<TreeNode>>>,
83+
val: i32,
84+
) -> Option<Rc<RefCell<TreeNode>>> {
85+
// Always return a node reference, never None.
86+
Some(match root {
87+
// We are at the insertion point, create and return a new node.
88+
None => Rc::new(RefCell::new(TreeNode {
89+
val,
90+
left: None,
91+
right: None,
92+
})),
93+
// We are traveling down the tree decide whether to go right or left,
94+
// create a new node with the result of calling insert_into_bst on the
95+
// child and update the current child with that result.
96+
Some(node_ref) => {
97+
if val < node_ref.borrow().val {
98+
let node = Self::insert_into_bst(node_ref.borrow().left.clone(), val);
99+
node_ref.borrow_mut().left = node;
100+
} else {
101+
let node = Self::insert_into_bst(node_ref.borrow().right.clone(), val);
102+
node_ref.borrow_mut().right = node;
103+
}
104+
node_ref
105+
}
106+
})
107+
}
108+
}
109+
110+
// Tests.
111+
fn main() {
112+
// assert_eq!(Solution::min_diff_in_bst(root), 1);
113+
println!("All tests passed!")
114+
}
115+
116+
// Definition for a binary tree node.
117+
#[derive(Debug, PartialEq, Eq)]
118+
pub struct TreeNode {
119+
pub val: i32,
120+
pub left: Option<Rc<RefCell<TreeNode>>>,
121+
pub right: Option<Rc<RefCell<TreeNode>>>,
122+
}
123+
124+
impl TreeNode {
125+
#[inline]
126+
pub fn new(val: i32) -> Self {
127+
TreeNode {
128+
val,
129+
left: None,
130+
right: None,
131+
}
132+
}
133+
}

leetcode/maximum-profit-in-job-scheduling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def jobScheduling(
112112
jobs = sorted(zip(startTime, endTime, profit), key=itemgetter(1))
113113
# At time 0 we can make at most 0 profit.
114114
dp = [(0, 0)]
115-
# Iterate over the jobs choosing wether to schedule them or skip
115+
# Iterate over the jobs choosing whether to schedule them or skip
116116
# them based on how they would affect the maximum profit.
117117
for start, end, p in jobs:
118118
# If we decided to use this job, what would be the max

0 commit comments

Comments
 (0)