Skip to content

Commit c79a2d3

Browse files
committed
initial tests completed
1 parent 081f359 commit c79a2d3

File tree

3 files changed

+52
-38
lines changed

3 files changed

+52
-38
lines changed

py3/median/median.py

+50-37
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,82 @@
11
class Solution:
2-
def single_place(self, nums, num):
3-
"""returns on which place >= num starts and how many same items"""
4-
lf, rg = 0, len(nums) - 1
2+
def bin_search(self, arr, num, fits=lambda a, b: a == b, le=lambda a, b: a <= b):
3+
"""
4+
returns tuple: the leftmost place of num in arr and the amount of items same an num
5+
"""
6+
lf, rg = 0, len(arr) - 1
57
md = (lf + rg) // 2
6-
while lf <= rg and nums[md] != num:
7-
if nums[md] <= num:
8+
while lf <= rg and not fits(arr[md], num):
9+
if le(arr[md], num):
810
lf = md + 1
911
else:
1012
rg = md - 1
1113
md = (lf + rg) // 2
1214

13-
if nums[md] == num:
14-
left_step, right_step = 1 >> 11, 1 >> 11
15-
lf_sum, rg_sum = 0, 0
15+
if fits(arr[md], num):
16+
# searching the biggest possible step to each side and do it as many times as possible
17+
left_step, right_step = 1 << 20, 1 << 20
18+
lf_offset, rg_offset = 0, 0
1619
while left_step and right_step:
17-
if md - left_step - lf_sum < 0 or nums[md - left_step - lf_sum] != num:
18-
left_step <<= 1
20+
if md - left_step - lf_offset < 0 or not fits(arr[md - left_step - lf_offset], num):
21+
left_step >>= 1
1922
else:
20-
lf_sum += left_step
23+
lf_offset += left_step
2124

22-
if md + right_step + rg_sum >= len(nums) or nums[md + right_step + rg_sum] != num:
23-
right_step <<= 1
25+
if md + right_step + rg_offset >= len(arr) or not fits(arr[md + right_step + rg_offset], num):
26+
right_step >>= 1
2427
else:
25-
rg_sum += right_step
26-
27-
return [md - lf_sum, rg_sum + lf_sum + 1]
28-
return [lf, 0]
28+
rg_offset += right_step
29+
return [md - lf_offset, rg_offset + lf_offset, True]
30+
return [lf, 0, False]
2931

3032
def place(self, nums1, nums2, num):
3133
"""returns the leftmost and the rightmost place of the element from nums1 in merged list"""
32-
place1, place2 = self.single_place(nums1, num), self.single_place(nums2, num)
33-
return [place1[0] + place2[0] + 2, place1[1] + place2[1]]
34+
place1, place2 = self.bin_search(nums1, num), self.bin_search(nums2, num)
35+
return [place1[0] + place2[0], place1[1] + int(place1[2]) + place2[1] + int(place2[2])]
3436

3537
def find_place(self, nums, other_nums, desired_place):
36-
lf, rg = 0, len(nums) - 1
37-
md = (lf + rg) // 2
38-
p = self.place(nums, other_nums, nums[md])
39-
while lf <= rg and not (p[0] <= desired_place <= p[0] + p[1]):
40-
if p[0] > desired_place:
41-
rg = md - 1
42-
else:
43-
lf = md + 1
44-
md = (lf + rg) // 2
45-
p = self.place(nums, other_nums, nums[md])
46-
return p
38+
class Shared:
39+
def __init__(self):
40+
self.p = None
41+
42+
def fits(self, a, b):
43+
self.p = Solution().place(nums, other_nums, a)
44+
return self.p[0] <= b < self.p[0] + self.p[1]
45+
46+
def le(self, _, b):
47+
return self.p[0] < b
48+
49+
s = Shared()
50+
p = self.bin_search(
51+
nums,
52+
desired_place,
53+
fits=s.fits,
54+
le=s.le
55+
)
56+
57+
if p[2]:
58+
return p
59+
return False
4760

4861
def findMedianSortedArrays(self, nums1, nums2, desired_place=None, need_two=None):
4962
if desired_place is None:
50-
desired_place = int((len(nums1) + len(nums2)) / 2.0 + 0.5)
63+
desired_place = int((len(nums1) + len(nums2)) / 2.0 + 0.5) - 1
5164
if need_two is None:
5265
need_two = (len(nums1) + len(nums2)) % 2 == 0
5366

5467
p = self.find_place(nums1, nums2, desired_place)
55-
if p[0] <= desired_place < p[0] + p[1]:
56-
second = nums1[p[0] - 1]
68+
if p:
69+
second = nums1[p[0]]
5770
if need_two:
5871
second = self.findMedianSortedArrays(nums1, nums2, desired_place=desired_place+1, need_two=False)
59-
return (nums1[p[0] - 1] + second) / 2.
72+
return (nums1[p[0]] + second) / 2.
6073

6174
p = self.find_place(nums2, nums1, desired_place)
62-
if p[0] <= desired_place < p[0] + p[1]:
63-
second = nums2[p[0] - 1]
75+
if p:
76+
second = nums2[p[0]]
6477
if need_two:
6578
second = self.findMedianSortedArrays(nums1, nums2, desired_place=desired_place+1, need_two=False)
66-
return (nums2[p[0] - 1] + second) / 2.
79+
return (nums2[p[0]] + second) / 2.
6780

6881
print("Something went wrong")
6982
return -1

py3/median/test/test1

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"input": "1 3\n2",
3-
"output": "2.00000"
3+
"output": "2.0"
44
}

py3/test.py

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def check_result(test):
3434
out = test.output.decode("ascii").strip()
3535
if test.expected == out:
3636
print_green(f"Test: {test.name} is [OK]")
37+
print_green(out)
3738
else:
3839
print_red(f"Test: {test.name} is [FAIL]")
3940
print_green(test.expected)

0 commit comments

Comments
 (0)