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: xuezaigds@gmail.com
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy