Skip to content

Commit 0cc1408

Browse files
Chris WuChris Wu
authored andcommitted
no message
1 parent b6a6e7f commit 0cc1408

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
"""
2+
On these two sorted arrays (`A` and `B`), we cut both of them into two part, left and right.
3+
`i` is the number of the element on the left of array `A`.
4+
`j` is the number of the element on the left of array `B`.
5+
`M` is the length of `A`.
6+
`N` is the length of `B`.
7+
Imagine if we find the median, and we use the median to seperate all the elements into two sides, left and right.
8+
9+
First, The number of elements on the left must equal to the right. That is:
10+
`Number of elements on the left of A` + `Number of elements on the left of B` is equal to `Number of elements on the right of A` + `Number of elements on the right of B`
11+
Thus `i + j == (M-i) + (N-j)`, so `j = (M+N)/2 - i`
12+
13+
Second, all the elements on the left must be smaller than the median. All the elements on the right must be larger than the median.
14+
The max on the left side of `A` must be <= the min on the right side of `B`.
15+
The max on the left side of `B` must be <= the min on the right side of `A`.
16+
Since both array is sorted, so alreay know
17+
the max on the left side of `A` must be <= to the min on the right side of `A`.
18+
the max on the left side of `B` must be <= the min on the right side of `B`.
19+
20+
For the coding part.
21+
Keep in mind again that **`i` is the number of the element on the left of array `A`.**
22+
And we can use `j = (M+N)/2 - i` to find `j`.
23+
We only need to use binary search to find the right `i` that matches
24+
```python
25+
max_left_A<=min_right_B and max_left_B<=min_right_A
26+
```
27+
And if `min_right_B<max_left_A`, it means that `i` is too large, so we adjust the upper limit of `i`, that is `h = i-1`.
28+
Otherwise it means that `i` is too small, so we adjust the lower limit of `i`, that is `l = i+1`.
29+
30+
Edge cases.
31+
I think this problem is particularly hard because of those complicated edge cases.
32+
33+
[0]
34+
We use the array with smaller length as our `A`.
35+
If not, the `j` might end up being negative.
36+
And we may binary search for fewer time, because `len(A)` is smaller
37+
38+
[1]
39+
What if `M+N` is odd, python will just truncate the float.
40+
If `M+N` is odd, no matter how we choose the median and cut both array into left and right.
41+
There will be one more left. In the `j = (M+N)/2-i` (floor) case, we will put the extra one on the right side.
42+
You may see some other solution using `j = (M+N+1)/2-i` (ceil), in that case, the extra one will be on the left side.
43+
So when `M+N` is odd using `j = (M+N)/2-i` the answer will be `min(min_right_A, min_right_B)`
44+
And using `j = (M+N+1)/2-i`, the anser will be `max(max_left_A, max_left_B)`
45+
46+
[2]
47+
There will be cases we end up `i == 0` (0 element on the left side of `A`), so we see it as the last element on the left side of `A` is negative infinity.
48+
There will be cases we end up `M-i == 0` (0 element on the right side of `A`), so we see it as the first element on the right side of `A` is infinity.
49+
50+
The time complexity is O(Log(min(M, N))).
51+
52+
"""
53+
class Solution(object):
54+
def findMedianSortedArrays(self, A, B):
55+
if len(A)>len(B): A, B = B, A #[0]
56+
57+
M, N = len(A), len(B)
58+
l, h = 0, M
59+
60+
while l<=h:
61+
i = (h+l)/2
62+
j = (M+N)/2-i #[1]
63+
64+
max_left_A = A[i-1] if i>0 else float('-inf') #[2]
65+
max_left_B = B[j-1] if j>0 else float('-inf')
66+
67+
min_right_A = A[i] if M-i>0 else float('inf')
68+
min_right_B = B[j] if N-j>0 else float('inf')
69+
70+
if max_left_A<=min_right_B and max_left_B<=min_right_A:
71+
if (M+N)%2==0:
72+
return (max(max_left_A, max_left_B)+min(min_right_A, min_right_B))/2.0
73+
else:
74+
return min(min_right_A, min_right_B) #[1]
75+
elif min_right_B<max_left_A:
76+
h = i-1
77+
else:
78+
l = i+1
79+
return None
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+
class Solution(object):
128+
def findMedianSortedArrays(self, X, Y):
129+
if len(X)>len(Y): X, Y = Y, X
130+
M, N = len(X), len(Y)
131+
132+
after = (M+N-1)/2
133+
l, h = 0, M
134+
135+
while l<h:
136+
i = (l+h)/2
137+
if after-i-1 < 0 or X[i] >= Y[after-i-1]:
138+
h = i
139+
else:
140+
l = i + 1
141+
i = l
142+
nextfew = sorted(X[i:i+2] + Y[after-i:after-i+2])
143+
return (nextfew[0]+nextfew[1-(M+N)%2])/2.0

0 commit comments

Comments
 (0)