-
Notifications
You must be signed in to change notification settings - Fork 820
/
MedianOfTwoSortedArrays.java
86 lines (81 loc) · 3.01 KB
/
MedianOfTwoSortedArrays.java
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
/* (C) 2024 YourCompanyName */
package binary_search;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by gouthamvidyapradhan on 23/05/2017. There are two sorted arrays nums1 and nums2 of size
* m and n respectively.
*
* <p>Find the median of the two sorted arrays. The overall run time complexity should be O(log
* (m+n)).
*
* <p>Example 1: nums1 = [1, 3] nums2 = [2]
*
* <p>The median is 2.0 Example 2: nums1 = [1, 2] nums2 = [3, 4]
*
* <p>The median is (2 + 3)/2 = 2.5
*
* <p>Solution: Works in worst case time complexity of O(log min(m, n))
*
* <p>The basic idea is that if you are given two arrays A and B and know the length of each, you
* can check whether an element A[i] is the median in constant time. Suppose that the median is
* A[i]. Since the array is sorted, it is greater than exactly i − 1 values in array A. Then if it
* is the median, it is also greater than exactly j = [n / 2] − (i − 1) elements in B. It requires
* constant time to check if B[j] A[i] <= B[j + 1]. If A[i] is not the median, then depending on
* whether A[i] is greater or less than B[j] and B[j + 1], you know that A[i] is either greater than
* or less than the median. Thus you can binary search for A[i] in O(log N) worst-case time
*/
public class MedianOfTwoSortedArrays {
/**
* Main method
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
int[] A = {1, 2, 5, 8, 44, 45, 45};
int[] B = {1, 2, 3, 4, 5, 6, 7, 23, 23, 23, 33, 44, 45, 45, 56, 77, 5555};
System.out.println(new MedianOfTwoSortedArrays().findMedianSortedArrays(A, B));
}
/**
* Find median
*
* @param nums1 array one
* @param nums2 array two
* @return
*/
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length)
return findMedianSortedArrays(nums2, nums1); // ensure always nums1 is the shortest array
int T = nums1.length + nums2.length, low = -1, high = -1;
int median = (T - 1) / 2;
boolean isOdd = false;
if ((T % 2) != 0) isOdd = true;
int s = 0, e = nums1.length - 1;
while (s <= e) {
int m = s + (e - s) / 2;
if ((median - m - 1) < 0 || nums1[m] >= nums2[median - m - 1]) {
e = m - 1;
low = m;
high = median - m;
} else s = m + 1;
}
if (low == -1) {
if (isOdd) return nums2[median - nums1.length];
else return (double) (nums2[median - nums1.length] + nums2[median - nums1.length + 1]) / 2.0D;
} else {
if (isOdd) return nums1[low] < nums2[high] ? nums1[low] : nums2[high];
else {
// Always sorts maximum of 4 elements hence works in O(1)
List<Integer> list = new ArrayList<>();
list.add(nums1[low]);
if (low + 1 < nums1.length) list.add(nums1[low + 1]);
list.add(nums2[high]);
if (high + 1 < nums2.length) list.add(nums2[high + 1]);
Collections.sort(list);
return (double) (list.get(0) + list.get(1)) / 2.0;
}
}
}
}