Skip to content

Commit 32d1154

Browse files
committed
refactor
1 parent 7d609e2 commit 32d1154

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+4715
-4771
lines changed

src/001.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# uncomments the following line when need to debug stack overflow error
2+
# import sys
3+
# sys.setrecursionlimit(10)
4+
5+
# 1 - 50
6+
"""
7+
!! question 1
8+
Given a list of numbers and a number k, return whether any two numbers from
9+
the list add up to k.
10+
For example, given [10, 15, 3, 7] and k of 17, return true since 10 + 7 is 17.
11+
Bonus: Can you do this in one pass?
12+
-------------------
13+
14+
## Understand the problem
15+
The input is a list of numbers and a number k, the output is a boolean...
16+
17+
## !! brain storming
18+
1. brute-force approach
19+
the most straight-forward approach is to find every possible pair of numbers
20+
in the list,
21+
For every pair check whether the sum is equal to k
22+
time O(n^2), space O(1)
23+
24+
2. sort the array and use two-pointers to find the pair that sum up to k.
25+
3, 7, 10, 15
26+
^
27+
^
28+
18 > 17, 13 < 17, 17 == 17 return true
29+
Time O(nlgn), space O(1)
30+
31+
3. !! to do this in one pass? This means we can only iterate the list once.
32+
We need an effective way to check whether we've already encountered the
33+
complement of the current number needed to reach K.
34+
So we can introduce a hashset data structure to add all the already-visited
35+
numvers to it.
36+
10, 15, 3, 7
37+
7 2 14 10 ^
38+
k=17
39+
set: [10, 15, 3] return true
40+
"""
41+
42+
43+
def test_1():
44+
pass

src/002.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""
2+
!! question 2
3+
Given an array of integers, return a new array such that each element at index
4+
i of the new array is the product of all the numbers in the original array
5+
except the one at i.
6+
7+
For example, if our input was [1, 2, 3, 4, 5],
8+
the expected output would be [120, 60, 40, 30, 24].
9+
If our input was [3, 2, 1], the expected output would be [2, 3, 6].
10+
11+
Follow-up: what if you can't use division?
12+
-------------------
13+
14+
## brainstorming
15+
1. brute-force: for every number, calculate the product of all the
16+
other number.
17+
time O(n^2), space O(1)
18+
2. in the brute force, we do many duplcated calculation:
19+
the product of the same numbers.
20+
if we can prevent the duplicated calculation we can optimize it.
21+
We can first calculate the product of all the numbers in the array.
22+
for every element, we only need to use the current nuber to divide
23+
the total product and get the result we need.
24+
time O(n), space O(1)
25+
3. what if we can't use division?
26+
brute-force approach doesn't use division, but can we optimize it?
27+
28+
formula for #2 is totalProduct/currentNumber
29+
new formula: product of numbers in its left * product of numbers
30+
in its right
31+
prefix and suffix products
32+
so we need two arrays, the first is the product of left numbers
33+
and the second is the product of right numbers.
34+
left_prod[i] = arr[0]*arr[1]..*arr[i-1]
35+
right_prod[i] = arr[i+1]* arr[i+2]...arr[n-1]
36+
output[i] = left_prod[i] * right_prod[i]
37+
38+
!! optimze space - in-place calculation
39+
do the calculation directly in the result
40+
result[0] = 1
41+
i from 1 to n-1:
42+
result[i] = result[i-1] * nums[i-1]
43+
prod = 1
44+
i form n-2 to 0:
45+
prod *= nums[i+1]
46+
result[i] *= prod
47+
48+
time O(n), space O(n)
49+
50+
edge case: if there is a zero in the input array, the approach without
51+
division works correctly without specific handling this case.
52+
"""
53+
54+
55+
def test_2():
56+
pass

src/003.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
question 3
3+
Given the root to a binary tree, implement serialize(root),
4+
which serializes the tree into a string,
5+
and deserialize(s), which deserializes the string back into the tree.
6+
7+
For example, given the following Node class
8+
9+
class Node:
10+
def __init__(self, val, left=None, right=None):
11+
self.val = val
12+
self.left = left
13+
self.right = right
14+
15+
The following test should pass:
16+
17+
node = Node('root', Node('left', Node('left.left')), Node('right'))
18+
assert deserialize(serialize(node)).left.left.val == 'left.left'
19+
"""
20+
21+
22+
def test_3():
23+
pass

src/004.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
question 4
3+
Given an array of integers, find the first missing positive integer in linear
4+
time and constant space. In other words, find the lowest positive integer
5+
that does not exist in the array. The array can contain duplicates
6+
and negative numbers as well.
7+
8+
For example, the input [3, 4, -1, 1] should give 2.
9+
The input [1, 2, 0] should give 3.
10+
11+
You can modify the input array in-place.
12+
-------------------
13+
14+
1 2 3 4
15+
2 3 1 4
16+
1 2 3 4
17+
[3, 4, -1, 1]
18+
[1, -1, 3, 4]
19+
for i in range():
20+
val = nums[i]
21+
if val in range(1, n+1):
22+
# swap elements in i and val+1
23+
nums[i] = i+1
24+
"""
25+
26+
27+
def findLowest(nums: int) -> int:
28+
n = len(nums)
29+
for i in range(n):
30+
while nums[i] in range(1, n + 1) and i + 1 != nums[i]:
31+
# swap element in i and nums[i]-1
32+
j = nums[i] - 1
33+
tt = nums[i]
34+
nums[i] = nums[j]
35+
nums[j] = tt
36+
for i in range(n):
37+
if nums[i] != i + 1:
38+
return i + 1
39+
return n + 1
40+
41+
42+
def test_4():
43+
assert findLowest([3, 4, -1, 1]) == 2
44+
assert findLowest([1, 2, 0]) == 3

src/005.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
question 5
3+
cons(a, b) constructs a pair, and car(pair) and cdr(pair) returns the
4+
first and last element of that pair. For example, car(cons(3, 4)) returns 3,
5+
and cdr(cons(3, 4)) returns 4.
6+
7+
Given this implementation of cons:
8+
9+
def cons(a, b):
10+
def pair(f):
11+
return f(a, b)
12+
return pair
13+
Implement car and cdr.
14+
15+
-------------------
16+
Understand the problem
17+
cons() return a function 'pair and 'pair' takes another function 'f' as input.
18+
So car() and cdr() need to provide its own impl of function 'f' and pass it to 'pair'.
19+
"""
20+
21+
22+
def cons(a, b):
23+
def pair(f):
24+
return f(a, b)
25+
26+
return pair
27+
28+
29+
def car(pair):
30+
def getFirst(a, b):
31+
return a
32+
33+
return pair(getFirst)
34+
35+
36+
def cdr(pair):
37+
def getSecond(a, b):
38+
return b
39+
40+
return pair(getSecond)
41+
42+
43+
def test_5():
44+
assert car(cons(3, 4)) == 3
45+
assert cdr(cons(3, 4)) == 4

src/006.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
question 6
3+
An XOR linked list is a more memory efficient doubly linked list.
4+
Instead of each node holding next and prev fields, it holds a field
5+
named both, which is an XOR of the next node and the previous node.
6+
Implement an XOR linked list; it has an add(element) which adds the
7+
element to the end, and a get(index) which returns the node at index.
8+
9+
If using a language that has no pointers (such as Python), you can assume
10+
you have access to get_pointer and dereference_pointer functions that
11+
converts between nodes and memory addresses.
12+
13+
both: an XOR of the next node and the pre node.
14+
how to get next node and pre node by both field?
15+
"""
16+
17+
18+
def test_6():
19+
pass

src/007.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
question 7
3+
Given the mapping a = 1, b = 2, ... z = 26, and an encoded message, count
4+
the number of ways it can be decoded.
5+
6+
For example, the message '111' would give 3, since it could be decoded
7+
as 'aaa', 'ka', and 'ak'.
8+
9+
You can assume that the messages are decodable. For example,
10+
'001' is not allowed.
11+
-------------------
12+
13+
[1, 26] valid code
14+
'1234'
15+
^
16+
f('n1n2...ni'):
17+
count = 0
18+
if int('n1') in range(1, 10):
19+
count += f('n2...ni')
20+
if int('n1n2') in range(10, 27):
21+
count += f('n3...ni')
22+
23+
dp = [0] * len(msg)
24+
'd1d2d3....dn'
25+
26+
if d1>0: dp(0) = 1
27+
28+
if d2>0: dp(1) += dp(0)
29+
if d1d2 in range(10, 27):
30+
dp(1) += 1
31+
32+
for i in range(2, len(msg)):
33+
if int(msg[i]) > 0:
34+
dp[i] += dp[i-1]
35+
if int(msg[i-1:i+1]) in range(10, 27):
36+
dp[i] += dp[i-2]
37+
return dp[len(msg)-1]
38+
"""
39+
40+
41+
def getDecodingWays(msg: str) -> int:
42+
dp0, dp1, dp2 = 1, 0, 0
43+
# '111' 1,2,3
44+
if int(msg[0]) > 0:
45+
dp1 = 1
46+
47+
for i in range(1, len(msg)):
48+
if int(msg[i]) > 0:
49+
dp2 += dp1
50+
if int(msg[i - 1 : i + 1]) in range(10, 27):
51+
dp2 += dp0
52+
dp0 = dp1
53+
dp1 = dp2
54+
dp2 = 0
55+
return dp1
56+
57+
58+
def test_7():
59+
assert getDecodingWays("111") == 3
60+
assert getDecodingWays("1111111") == 21

src/008.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""
2+
question 8
3+
A unival tree (which stands for "universal value") is a tree where
4+
all nodes under it have the same value.
5+
Given the root to a binary tree, count the number of unival subtrees.
6+
For example, the following tree has 5 unival subtrees:
7+
0
8+
/ \
9+
1 0
10+
/ \
11+
1 0
12+
/ \
13+
1 1
14+
-------------------
15+
16+
first element means whether the tree is unival tree or not.
17+
second element means the number of unival tree in this tree
18+
[True|False, int]
19+
20+
f(node):
21+
if isLeaf: return [True, 0]
22+
23+
if node.left:
24+
return [False, f(node.left)[1]]
25+
elif node.right:
26+
return [False, f(node.right)[1]]
27+
# both left and right not None
28+
29+
"""
30+
31+
32+
class TreeNode:
33+
def __init__(self, val: int, left: object = None, right: object = None):
34+
self.val = val
35+
self.left = left
36+
self.right = right
37+
38+
def print(self):
39+
print(self.val)
40+
41+
def print_inorder(self):
42+
if self.left:
43+
self.print_inorder(self.left)
44+
self.print()
45+
if self.right:
46+
self.print_inorder(self.right)
47+
48+
49+
def getUnivalTreeNum(node: object) -> int:
50+
def dfs(node: object) -> list:
51+
if not node:
52+
return [True, 0]
53+
# leaf node
54+
if not node.left and not node.right:
55+
return [True, 1]
56+
57+
# handle one subtree is None.
58+
if not node.left:
59+
return [False, dfs(node.right)[1]]
60+
elif not node.right:
61+
return [False, dfs(node.left)[1]]
62+
63+
# handle both subtrees are not None
64+
rtn = dfs(node.left)
65+
isLeftUnival, leftCount = rtn
66+
rtn = dfs(node.right)
67+
isRightUnival, rightCount = rtn
68+
total = leftCount + rightCount
69+
isUnival = False
70+
if isLeftUnival and isRightUnival and node.left.val == node.right.val:
71+
isUnival = True
72+
total += 1
73+
return [isUnival, total]
74+
75+
return dfs(node)[1]
76+
77+
78+
def test_8():
79+
root = TreeNode(
80+
0,
81+
left=TreeNode(1),
82+
right=TreeNode(
83+
0, left=TreeNode(1, left=TreeNode(1), right=TreeNode(1)), right=TreeNode(0)
84+
),
85+
)
86+
assert getUnivalTreeNum(root) == 5

0 commit comments

Comments
 (0)