Skip to content

Commit 7b59ca8

Browse files
committed
update 4. Median of Two Sorted Arrays
1 parent a2d57eb commit 7b59ca8

File tree

4 files changed

+260
-58
lines changed

4 files changed

+260
-58
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* @Author: [email protected]
3+
* @Last Modified time: 2016-07-10 14:33:58
4+
*/
5+
6+
class Solution {
7+
public:
8+
/*
9+
Divide and Conquer inspired by find k-th number in sorted array.
10+
11+
The complexity is of course O(log(M+N)).
12+
Similiar with the following answer except without slicing.
13+
https://discuss.leetcode.com/topic/6947/intuitive-python-o-log-m-n-solution-by-kth-smallest-in-the-two-sorted-arrays-252ms
14+
*/
15+
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
16+
int len1 = nums1.size();
17+
int len2 = nums2.size();
18+
int len = len1 + len2;
19+
if(len & 0x1 == 1){
20+
return find_kth(nums1, 0, len1, nums2, 0, len2, (len+1)/2);
21+
}
22+
else{
23+
return (find_kth(nums1, 0, len1, nums2, 0, len2, (len)/2) +
24+
find_kth(nums1, 0, len1, nums2, 0, len2, (len)/2+1)) / 2.0;
25+
}
26+
}
27+
28+
int find_kth(vector<int>& list1, int begin1, int end1,
29+
vector<int>& list2, int begin2, int end2, int k){
30+
/*
31+
Find the kth number in two sorted list: list1 , list2
32+
33+
Binary search as followers:
34+
Firstly cut list1 and list2 into two parts by t1 and t2, respectively.
35+
1. lis1_left ... list1[t1-th] ... list1_right,
36+
2. lis2_left ... list2[t2-th] ... list2_right
37+
Then compare value of list1[t1-th] and list2[t2-th] in list2.
38+
Three situations about the relation between list1[t1-th] and list2[t2-th]:
39+
1. < Equal the (k-t1)th number in list1_right and list_2 left.
40+
2. > Equal the (k-t2)th number in list1_left and list_2 right.
41+
3. == Find the k-th number.
42+
*/
43+
int len1 = end1 - begin1;
44+
int len2 = end2 - begin2;
45+
if(len1 > len2){
46+
return find_kth(list2, begin2, end2, list1, begin1, end1, k);
47+
}
48+
if(len1 == 0){
49+
return list2[begin2+k-1];
50+
}
51+
if(k==1){
52+
return min(list1[begin1], list2[begin2]);
53+
}
54+
55+
int t1 = min(k/2, len1);
56+
int t2 = k - t1;
57+
if(list1[begin1+t1-1] < list2[begin2+t2-1]){
58+
return find_kth(list1, begin1+t1, end1, list2, begin2, begin2+t2, k-t1);
59+
}
60+
else if(list1[begin1+t1-1] > list2[begin2+t2-1]){
61+
return find_kth(list1, begin1, begin1+t1, list2, begin2+t2, end2, k-t2);
62+
}
63+
else{
64+
return list1[begin1+t1-1];
65+
}
66+
}
67+
};
68+
69+
70+
/*
71+
[]
72+
[1]
73+
[1,3]
74+
[2]
75+
[1]
76+
[2,3,4,5,6]
77+
[2,3,4]
78+
[5,6,7]
79+
*/
80+
81+
82+
/*
83+
Excellent explanation can be found here:
84+
https://discuss.leetcode.com/topic/4996/share-my-o-log-min-m-n-solution-with-explanation
85+
86+
In statistics, the median is used for dividing a set into two equal length subsets,
87+
that one subset is always greater than the other.
88+
89+
First let's cut A into two parts at a random position i:
90+
91+
left_A | right_A
92+
A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1]
93+
Since A has m elements, so there are m+1 kinds of cutting( i = 0 ~ m ).
94+
And we know: len(left_A) = i, len(right_A) = m - i .
95+
Note: when i = 0 , left_A is empty, and when i = m , right_A is empty.
96+
97+
With the same way, cut B into two parts at a random position j:
98+
99+
left_B | right_B
100+
B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
101+
102+
Put left_A and left_B into one set, and put right_A and right_B into another set.
103+
Let's name them left_part and right_part :
104+
105+
left_part | right_part
106+
A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1]
107+
B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
108+
109+
If we can ensure:
110+
111+
1) len(left_part) == len(right_part)
112+
2) max(left_part) <= min(right_part)
113+
114+
then we divide all elements in {A, B} into two parts with equal length,
115+
and one part is always greater than the other.
116+
Then median = (max(left_part) + min(right_part))/2.
117+
118+
To ensure these two conditions, we just need to ensure:
119+
120+
(1) i + j == m - i + n - j (or: m - i + n - j + 1)
121+
if n >= m, we just need to set: i = 0 ~ m, j = (m + n + 1)/2 - i
122+
(2) B[j-1] <= A[i] and A[i-1] <= B[j]
123+
(For simplicity, I presume A[i-1],B[j-1],A[i],B[j] are
124+
always valid even if i=0/i=m/j=0/j=n .
125+
I will talk about how to deal with these edge values at last.)
126+
127+
So, all we need to do is:
128+
129+
Searching i in [0, m], to find an object `i` that:
130+
B[j-1] <= A[i] and A[i-1] <= B[j], ( where j = (m + n + 1)/2 - i )
131+
132+
When the object i is found, the median is:
133+
max(A[i-1], B[j-1]) (when m + n is odd)
134+
or (max(A[i-1], B[j-1]) + min(A[i], B[j]))/2 (when m + n is even)
135+
*/
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#! /usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
5+
class Solution(object):
6+
""" Divide and Conquer inspired by find k-th number in sorted array.
7+
8+
The complexity is of course O(log(M+N)).
9+
Similiar with the following answer except without slicing.
10+
https://discuss.leetcode.com/topic/6947/intuitive-python-o-log-m-n-solution-by-kth-smallest-in-the-two-sorted-arrays-252ms
11+
"""
12+
13+
def findMedianSortedArrays(self, nums1, nums2):
14+
n1, n2 = len(nums1), len(nums2)
15+
length = n1 + n2
16+
17+
if length & 0x1:
18+
return self.find_kth_num(nums1, 0, n1, nums2, 0, n2, (length + 1) / 2)
19+
else:
20+
return (self.find_kth_num(nums1, 0, n1, nums2, 0, n2, length / 2) +
21+
self.find_kth_num(nums1, 0, n1, nums2, 0, n2, length / 2 + 1)) / 2.0
22+
23+
def find_kth_num(self, list1, begin1, end1, list2, begin2, end2, k):
24+
""" Find the kth number in two sorted list: list1 , list2
25+
26+
Binary search as followers:
27+
Firstly cut list1 and list2 into two parts by t1 and t2, respectively.
28+
1. lis1_left ... list1[t1-th] ... list1_right,
29+
2. lis2_left ... list2[t2-th] ... list2_right
30+
Then compare value of list1[t1-th] and list2[t2-th] in list2.
31+
Three situations about the relation between list1[t1-th] and list2[t2-th]:
32+
1. < Equal the (k-t1)th number in list1_right and list_2 left.
33+
2. > Equal the (k-t2)th number in list1_left and list_2 right.
34+
3. == Find the k-th number.
35+
"""
36+
n1, n2 = end1 - begin1, end2 - begin2
37+
38+
# Make sure the first list is always shorter than the second
39+
if n1 > n2:
40+
return self.find_kth_num(list2, begin2, end2, list1, begin1, end1, k)
41+
if n1 == 0:
42+
return list2[begin2 + k - 1]
43+
if k == 1:
44+
return min(list1[begin1], list2[begin2])
45+
46+
# Get the next search interval
47+
t1 = min(k / 2, n1)
48+
t2 = k - t1
49+
if list1[begin1 + t1 - 1] < list2[begin2 + t2 - 1]:
50+
return self.find_kth_num(list1, begin1 + t1, end1, list2, begin2, begin2 + t2, k - t1)
51+
elif list1[begin1 + t1 - 1] > list2[begin2 + t2 - 1]:
52+
return self.find_kth_num(list1, begin1, begin1 + t1, list2, begin2 + t2, end2, k - t2)
53+
else:
54+
return list1[begin1 + t1 - 1]
55+
56+
57+
"""
58+
[]
59+
[1]
60+
[1,3]
61+
[2]
62+
[1]
63+
[2,3,4,5,6]
64+
[2,3,4]
65+
[5,6,7]
66+
"""
67+
68+
69+
"""
70+
Excellent explanation can be found here:
71+
https://discuss.leetcode.com/topic/4996/share-my-o-log-min-m-n-solution-with-explanation
72+
73+
In statistics, the median is used for dividing a set into two equal length subsets,
74+
that one subset is always greater than the other.
75+
76+
First let's cut A into two parts at a random position i:
77+
78+
left_A | right_A
79+
A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1]
80+
Since A has m elements, so there are m+1 kinds of cutting( i = 0 ~ m ).
81+
And we know: len(left_A) = i, len(right_A) = m - i .
82+
Note: when i = 0 , left_A is empty, and when i = m , right_A is empty.
83+
84+
With the same way, cut B into two parts at a random position j:
85+
86+
left_B | right_B
87+
B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
88+
89+
Put left_A and left_B into one set, and put right_A and right_B into another set.
90+
Let's name them left_part and right_part :
91+
92+
left_part | right_part
93+
A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1]
94+
B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
95+
96+
If we can ensure:
97+
98+
1) len(left_part) == len(right_part)
99+
2) max(left_part) <= min(right_part)
100+
101+
then we divide all elements in {A, B} into two parts with equal length,
102+
and one part is always greater than the other.
103+
Then median = (max(left_part) + min(right_part))/2.
104+
105+
To ensure these two conditions, we just need to ensure:
106+
107+
(1) i + j == m - i + n - j (or: m - i + n - j + 1)
108+
if n >= m, we just need to set: i = 0 ~ m, j = (m + n + 1)/2 - i
109+
(2) B[j-1] <= A[i] and A[i-1] <= B[j]
110+
(For simplicity, I presume A[i-1],B[j-1],A[i],B[j] are
111+
always valid even if i=0/i=m/j=0/j=n .
112+
I will talk about how to deal with these edge values at last.)
113+
114+
So, all we need to do is:
115+
116+
Searching i in [0, m], to find an object `i` that:
117+
B[j-1] <= A[i] and A[i-1] <= B[j], ( where j = (m + n + 1)/2 - i )
118+
119+
When the object i is found, the median is:
120+
max(A[i-1], B[j-1]) (when m + n is odd)
121+
or (max(A[i-1], B[j-1]) + min(A[i], B[j]))/2 (when m + n is even)
122+
"""

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
* 058. [Length of Last Word](String/58_LengthOfLastWord.py)
2727
* 067. [Add Binary](String/67_AddBinary.py)
2828
* 068. Text Justification
29-
* 069. [Sqrt(x)](BinarySearch/69_Sqrt_x.py)
3029
* 151. [Reverse Words in a String](String/151_ReverseWordsInString.py)
3130
* 165. [Compare Version Numbers](String/165_CompareVersionNumbers.py)
3231
* 344. [Reverse String](String/344_ReverseString.py)
@@ -112,10 +111,11 @@
112111

113112
# [Binary Search](BinarySearch/)
114113

114+
* 004. [Median of Two Sorted Arrays](BinarySearch/4_MedianOfTwoSortedArrays.py)
115+
* 033. Search in Rotated Sorted Array
115116
* 034. [Search for a Range](BinarySearch/34_SearchForRange.py)
116-
* 069. Sqrt(x)
117+
* 069. [Sqrt(x)](BinarySearch/69_Sqrt_x.py)
117118
* 074. [Search a 2D Matrix](BinarySearch/74_Search2DMatrix.py)
118-
* 033. Search in Rotated Sorted Array
119119
* 081. [Search in Rotated Sorted Array II](BinarySearch/81_SearchInRotatedSortedArrayII.py)
120120
* 153. [Find Minimum in Rotated Sorted Array](BinarySearch/153_FindMinimumInRotatedSortedArray.py)
121121
* 154. [Find Minimum in Rotated Sorted Array II](BinarySearch/154_FindMinimumInRotatedSortedArrayII.py)

Week04/4.py

Lines changed: 0 additions & 55 deletions
This file was deleted.

0 commit comments

Comments
 (0)