|
4 | 4 | */
|
5 | 5 | class Solution {
|
6 | 6 | public double findMedianSortedArrays(int[] nums1, int[] nums2) {
|
7 |
| - // Ensure nums1 has the greater length |
| 7 | + // Ensure nums1 is always shorter than nums2 for simplicity |
8 | 8 | if (nums1.length > nums2.length) {
|
9 |
| - int [] tmp = nums1; |
| 9 | + int[] tmp = nums1; |
10 | 10 | nums1 = nums2;
|
11 | 11 | nums2 = tmp;
|
12 | 12 | }
|
13 | 13 |
|
| 14 | + // Init pointers for partitions. |
| 15 | + // lo, will start at the first index |
| 16 | + // hi, will start at the end of nums1 as if the first index of nums2 |
14 | 17 | int lo = 0;
|
15 | 18 | int hi = nums1.length;
|
16 | 19 | int combinedLen = nums1.length + nums2.length;
|
17 | 20 |
|
| 21 | + // Loop until both pointers meet |
18 | 22 | while (lo <= hi) {
|
19 |
| - int partX = (lo + hi) / 2; |
20 |
| - int partY = (combinedLen + 1) / 2 - partX; |
| 23 | + // nums1 being the shortest array, midX represents mid index of nums1 |
| 24 | + // midX = the mid index of nums1 |
| 25 | + // midY = the mid index of nums2 |
| 26 | + // |
| 27 | + // Example 1 |
| 28 | + // |
| 29 | + // nums1: [1, 3] |
| 30 | + // ↑ midX |
| 31 | + // nums2: [2] |
| 32 | + // ↑ midY |
| 33 | + // |
| 34 | + // Combined sorted: [1, 2, 3] |
| 35 | + // midX ↑ ↑ midY |
| 36 | + // |
| 37 | + // Example 2 |
| 38 | + // |
| 39 | + // nums1: [1, 2] |
| 40 | + // ↑ midX |
| 41 | + // nums2: [3, 4] |
| 42 | + // ↑ midY |
| 43 | + // |
| 44 | + // Combined sorted: [1, 2, 3, 4, 5] |
| 45 | + // midx ↑ ↑ midY |
| 46 | + // |
21 | 47 |
|
22 |
| - int leftX = getMax(nums1, partX); |
23 |
| - int rightX = getMin(nums1, partX); |
| 48 | + // System.out.println("lo: " + lo + ",\t\t\thi: " + hi); |
| 49 | + int midX = (lo + hi) / 2; |
| 50 | + int midY = (combinedLen + 1) / 2 - midX; |
24 | 51 |
|
25 |
| - int leftY = getMax(nums2, partY); |
26 |
| - int rightY = getMin(nums2, partY); |
| 52 | + // System.out.println("midX: " + midX + ",\t\tmidY: " + midY); |
27 | 53 |
|
| 54 | + // getMax and getMin ensures that even when we are at the ends of the |
| 55 | + // arrays, we still get a value that will not mess up the array while |
| 56 | + // preventing index out of bounds. |
| 57 | + int leftX = getMax(nums1, midX); |
| 58 | + int rightX = getMin(nums1, midX); |
| 59 | + |
| 60 | + // System.out.println("leftX: " + leftX + ",\trightX: " + rightX); |
| 61 | + |
| 62 | + int leftY = getMax(nums2, midY); |
| 63 | + int rightY = getMin(nums2, midY); |
| 64 | + |
| 65 | + // System.out.println("leftY: " + leftY + ",\t\trightY: " + rightY); |
| 66 | + |
| 67 | + // If both pointers crosses or met each other. Meaning we are at the |
| 68 | + // middle of the combined sorted arrays. |
28 | 69 | if (leftX <= rightY && leftY <= rightX) {
|
29 |
| - if (combinedLen % 2 == 0) { |
| 70 | + // Handle even length |
| 71 | + if (combinedLen % 2 == 0) |
30 | 72 | return (Math.max(leftX, leftY) + Math.min(rightX, rightY)) / 2.0;
|
31 |
| - } |
32 |
| - return Math.max(leftX, leftY); |
33 |
| - } |
34 |
| - |
35 |
| - if (leftX > rightY) { |
36 |
| - hi = partX - 1; |
37 |
| - } else { |
38 |
| - lo = partX + 1; |
| 73 | + else |
| 74 | + return Math.max(leftX, leftY); |
39 | 75 | }
|
40 | 76 |
|
| 77 | + // Scoot over pointers if median not yet found |
| 78 | + if (leftX > rightY) |
| 79 | + hi = midX - 1; |
| 80 | + else |
| 81 | + lo = midX + 1; |
41 | 82 | }
|
42 | 83 |
|
| 84 | + // Return -1 if not sorted or failed |
43 | 85 | return -1;
|
44 | 86 | }
|
45 | 87 |
|
46 |
| - private int getMax(int[] nums, int partition) { |
47 |
| - if (partition == 0) { |
| 88 | + // Returns the value BEFORE (let) the given idx or NEGATIVE_INFINITY if |
| 89 | + // idx < 0 |
| 90 | + private int getMax(int[] nums, int idx) { |
| 91 | + if (idx == 0) { |
48 | 92 | return (int)Double.NEGATIVE_INFINITY;
|
49 | 93 | } else {
|
50 |
| - return nums[partition - 1]; |
| 94 | + return nums[idx - 1]; |
51 | 95 | }
|
52 | 96 | }
|
53 | 97 |
|
54 |
| - private int getMin(int[] nums, int partition) { |
55 |
| - if (partition == nums.length) { |
| 98 | + // Returns the value AFTER (right) the given idx or POSITIVE_INFINITY if |
| 99 | + // idx == nums.length |
| 100 | + private int getMin(int[] nums, int idx) { |
| 101 | + if (idx == nums.length) { |
56 | 102 | return (int)Double.POSITIVE_INFINITY;
|
57 | 103 | } else {
|
58 |
| - return nums[partition]; |
| 104 | + return nums[idx]; |
59 | 105 | }
|
60 | 106 | }
|
61 | 107 | }
|
0 commit comments