Skip to content

Commit 5bc94d0

Browse files
committed
8/26/23
- search_entry_equal_to_index.py - search_first_key.py - search_shifted_sorted_array.py - int_square_root.py - search_row_col_sorted_matrix.py
1 parent a7ec852 commit 5bc94d0

File tree

6 files changed

+160
-17
lines changed

6 files changed

+160
-17
lines changed

elements-of-programming-interviews/problem_mapping.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1308,7 +1308,7 @@ problem_mapping = {
13081308
"total": 314
13091309
},
13101310
"Python: search_first_key.py": {
1311-
"passed": 0,
1311+
"passed": 314,
13121312
"total": 314
13131313
}
13141314
},
@@ -1322,7 +1322,7 @@ problem_mapping = {
13221322
"total": 501
13231323
},
13241324
"Python: search_entry_equal_to_index.py": {
1325-
"passed": 0,
1325+
"passed": 501,
13261326
"total": 501
13271327
}
13281328
},
@@ -1336,7 +1336,7 @@ problem_mapping = {
13361336
"total": 307
13371337
},
13381338
"Python: search_shifted_sorted_array.py": {
1339-
"passed": 0,
1339+
"passed": 307,
13401340
"total": 307
13411341
}
13421342
},
@@ -1350,7 +1350,7 @@ problem_mapping = {
13501350
"total": 2000
13511351
},
13521352
"Python: int_square_root.py": {
1353-
"passed": 0,
1353+
"passed": 2000,
13541354
"total": 2000
13551355
}
13561356
},
@@ -1378,7 +1378,7 @@ problem_mapping = {
13781378
"total": 194
13791379
},
13801380
"Python: search_row_col_sorted_matrix.py": {
1381-
"passed": 0,
1381+
"passed": 194,
13821382
"total": 194
13831383
}
13841384
},

elements-of-programming-interviews/python/int_square_root.py

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
11
from test_framework import generic_test
22

33

4+
"""
5+
Adapt binary search
6+
if m*m > k, choose lower, no solution
7+
if m*m == k, return m
8+
if m*m < k choose upper, but m might be candidate
9+
"""
10+
11+
412
def square_root(k: int) -> int:
5-
# TODO - you fill in here.
6-
return 0
13+
lo, hi = 0, k
14+
# ensures we examine all possible candidates
15+
while lo <= hi:
16+
m = (hi + lo) // 2
17+
if m*m > k:
18+
# m is definitely not a solution
19+
hi = m-1
20+
elif m*m == k:
21+
return m
22+
else: # m*m < k
23+
# m might be a solution; we exclude it for
24+
# now, but hi will pick it up when hi < lo
25+
# if it's the best solution.
26+
lo = m+1
27+
return hi
728

829

930
if __name__ == '__main__':

elements-of-programming-interviews/python/search_entry_equal_to_index.py

+25-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,31 @@
66
from test_framework.test_utils import enable_executor_hook
77

88

9-
def search_entry_equal_to_its_index(A: List[int]) -> int:
10-
# TODO - you fill in here.
11-
return 0
9+
"""
10+
Suppose i < j < k
11+
If arr[j] > j, we know that every subsequent arr[k] > k, so no candidates are there.
12+
If arr[j] > j, we know nothing about arr[i] and i, unless the array is contiguous (which it isn't)
13+
14+
If arr[j] < j, then this is also true for every arr[i] and i, but we know nothing about arr[k] and k.
15+
16+
So do a standard binary search but:
17+
if arr[mid] > mid: pick lower
18+
if arr[mid] == mid, that's our answer.
19+
if arr[mid] < mid, pick higher.
20+
"""
21+
22+
23+
def search_entry_equal_to_its_index(arr: List[int]) -> int:
24+
l, r = 0, len(arr)-1
25+
while l <= r:
26+
mid = l + ((r-l) // 2)
27+
if arr[mid] > mid:
28+
r = mid - 1
29+
elif arr[mid] == mid:
30+
return mid
31+
else: # arr[mid] < mid
32+
l = mid + 1
33+
return -1
1234

1335

1436
@enable_executor_hook

elements-of-programming-interviews/python/search_first_key.py

+69-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,79 @@
33
from test_framework import generic_test
44

55

6+
"""
7+
Approaches
8+
- Linear search
9+
- Binary search to first element, linear search
10+
left from there.
11+
- Modified binary search?
12+
"""
13+
14+
import random
15+
16+
17+
def linear_search(A: List[int], k: int) -> int:
18+
i = 0
19+
while i < len(A):
20+
if A[i] == k:
21+
return i
22+
i += 1
23+
return -1
24+
25+
26+
def bin_then_linear_search(A: List[int], k: int) -> int:
27+
l, r = 0, len(A)-1
28+
while l <= r:
29+
m = (l+r) // 2
30+
if A[m] > k:
31+
r = m-1
32+
elif A[m] < k:
33+
l = m+1
34+
elif A[m] == k:
35+
while m > 0 and A[m-1] == k:
36+
m -= 1
37+
return m
38+
return -1
39+
40+
641
def search_first_of_k(A: List[int], k: int) -> int:
7-
# TODO - you fill in here.
8-
return 0
42+
if not A:
43+
return -1
44+
l, r = 0, len(A)-1
45+
m = -1
46+
while l < r:
47+
m = (l+r) // 2
48+
if A[m] > k:
49+
r = m-1
50+
elif A[m] == k:
51+
r = m
52+
else: # A[m] < k:
53+
l = m+1
54+
return -1 if A[l] != k else l
55+
56+
57+
def binary_search(A: List[int], k: int) -> int:
58+
l, r = 0, len(A)-1
59+
while l <= r:
60+
# l + r can overflow, but not in Python
61+
m = l + ((r-l) // 2)
62+
if A[m] > k:
63+
r = m-1
64+
elif A[m] == k:
65+
return m
66+
else: # A[m] < k:
67+
l = m+1
68+
return -1
969

1070

1171
if __name__ == '__main__':
72+
"""
73+
arr = sorted([random.randint(-100, 100) for _ in range(random.randint(0, 100))])
74+
k = arr[random.randint(0, len(arr)-1)]
75+
expected = linear_search(arr, k)
76+
actual = search_first_of_k(arr, k)
77+
assert expected == actual, f"{actual} != {expected}\nk = {k}\n{arr}"
78+
"""
1279
exit(
1380
generic_test.generic_test_main('search_first_key.py',
1481
'search_first_key.tsv',

elements-of-programming-interviews/python/search_row_col_sorted_matrix.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,20 @@
33
from test_framework import generic_test
44

55

6-
def matrix_search(A: List[List[int]], x: int) -> bool:
7-
# TODO - you fill in here.
8-
return True
6+
def matrix_search(A: List[List[int]], tgt: int) -> bool:
7+
y = 0
8+
x = len(A[0])-1
9+
10+
while y < len(A) and x >= 0:
11+
curr = A[y][x]
12+
if curr == tgt:
13+
return True
14+
elif curr > tgt:
15+
x -= 1
16+
else: # curr < tgt
17+
y += 1
18+
19+
return False
920

1021

1122
if __name__ == '__main__':

elements-of-programming-interviews/python/search_shifted_sorted_array.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,32 @@
22

33
from test_framework import generic_test
44

5+
"""
6+
- In sorted array, arr[0] is smallest element
7+
- Rotating the array moves smallest elsewhere.
8+
- If arr[l] > arr[r], the smallest is somewhere in the middle.
9+
10+
[9,0,1,2,3,4,5,6,7,8]
11+
"""
12+
513

614
def search_smallest(A: List[int]) -> int:
7-
# TODO - you fill in here.
8-
return 0
15+
l, r = 0, len(A)-1
16+
if A[l] <= A[r]:
17+
return 0
18+
19+
# if l == r, we found the only candidate
20+
while l < r:
21+
m = l + ((r-l) // 2)
22+
23+
if A[m] > A[r]:
24+
# A[m] is definitely not the minimum element.
25+
l = m+1
26+
else:
27+
# A[m] <= A[r]; A[m] might be the
28+
# min element, but we don't know yet.
29+
r = m
30+
return l
931

1032

1133
if __name__ == '__main__':

0 commit comments

Comments
 (0)