-
Notifications
You must be signed in to change notification settings - Fork 3
/
median_two_sorted_arrays_stress.py
139 lines (117 loc) · 3.84 KB
/
median_two_sorted_arrays_stress.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
class Naive(object):
def findMedianSortedArrays(self, nums1, nums2):
nums = nums1 + nums2
nums.sort()
size = len(nums)
if size % 2 == 1:
return float(nums[size//2])
return 0.5*(nums[size//2-1] + nums[size//2])
class Solution(object):
def isNotHeadTailCondition(self, X, Y, nX, nY):
"""Check for the negative of the head-tail condition."""
return nX > 0 and nY < len(Y) and X[nX-1] > Y[nY]
def getMergeSortArrayValue(self, A, B, nA, nB):
"""Get the value of merge-sort array."""
if nA == 0:
value = B[nB-1]
elif nB == 0:
value = A[nA-1]
else:
value = max(A[nA-1], B[nB-1])
return value
def mergeSortMap(self, A, B, n):
"""Help to find the median between arrays."""
# Array size
SA = len(A)
SB = len(B)
# Sanity check
if SA == 0 and SB == 0:
raise Exception('empty both arrays')
if n < 1 or n > SA + SB:
raise IndexError('merge-sort map index out of range')
# Edge case one empty array
if SA == 0:
return B[n-1]
if SB == 0:
return A[n-1]
# Check swap arrays to keep A as smaller array
if SA > SB:
SA, SB = SB, SA
A, B = B, A
# Interval initialization
left = 0
right = min(n, SA)
# Binary search
while 1:
# Binapartition of nA range
nA = (left + right)//2
# Derive value for nB
nB = n - nA
# Check if nB is out of range,
# meaning nA too small.
if nB > SB:
left = nA + 1
# Check if first head/tail condition tails
# meaning that nA is too large
elif self.isNotHeadTailCondition(A, B, nA, nB):
right = nA - 1
# Check if first head/tail condition tails
# meaning that nA is too small
elif self.isNotHeadTailCondition(B, A, nB, nA):
left = nA + 1
# Break if all conditions are met
else:
break
# Get the value of merge-sort array
return self.getMergeSortArrayValue(A, B, nA, nB)
def findMedianSortedArrays(self, A, B):
"""Compute the median of two sorted arrays."""
S = len(A) + len(B)
return 0.5 * (
self.mergeSortMap(A, B, ((S-1)//2)+1) +\
self.mergeSortMap(A, B, (S//2)+1)
)
import random
import time
random.seed(1234)
random.getstate()
tries = 10
size = 4000000
maxv = 10000000
#size = 1000
#maxv = 400
agg_naive = 0.0
agg_solution = 0.0
for n in range(tries):
val = random.randint(0,maxv)
size1 = random.randint(0,size)
size2 = random.randint(0,size)
if size1 == 0 and size2 == 0:
continue
nums1 = [random.randint(-val,val) for i in range(size1)]
nums2 = [random.randint(-val,val) for i in range(size2)]
nums1.sort()
nums2.sort()
#print('A = {}'.format(nums1))
#print('B = {}'.format(nums2))
start = time.time()
naive = Naive().findMedianSortedArrays(nums1, nums2)
naive_time = time.time()
solution = Solution().findMedianSortedArrays(nums1, nums2)
solution_time = time.time()
speedup = (naive_time - start)/\
(solution_time - naive_time)
agg_naive += naive_time - start
agg_solution += solution_time - naive_time
if naive == solution:
print('naive = {}, solution = {} (x{})'.format(
naive, solution, speedup
))
print('ok')
else:
print('naive = {}, solution = {}'.format(naive, solution))
print('bad')
break
print('naive time = {}'.format(agg_naive))
print('solution time = {}'.format(agg_solution))
print('agg speedup = {}'.format(agg_naive/agg_solution))