[LeetCode]4.尋找兩個正序陣列的中位數(Java)
阿新 • • 發佈:2021-10-18
LeetCode 04
原題地址: median-of-two-sorted-arrays
題目描述:
示例 1:
輸入:nums1 = [1,3], nums2 = [2]
輸出:2.00000
解釋:合併陣列 = [1,2,3] ,中位數 2
示例 2:
輸入:nums1 = [1,2], nums2 = [3,4]
輸出:2.50000
解釋:合併陣列 = [1,2,3,4] ,中位數 (2 + 3) / 2 = 2.5
示例 3:
輸入:nums1 = [0,0], nums2 = [0,0]
輸出:0.00000
提示:
nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106
進階:你能設計一個時間複雜度為 O(log (m+n)) 的演算法解決此問題嗎?
解答方法:
1.nums1,nums2合併後排序
時間複雜度:遍歷全部陣列 O(m+n)
空間複雜度:開闢了一個數組,儲存合併後的兩個陣列 O(m+n)
class Solution { public double findMedianSortedArrays(int[] nums1, int[] nums2) { int[] res=new int[nums1.length + nums2.length]; int n = 0; int len = nums1.length + nums2.length; for (int i = 0; i < nums1.length; i++){ res[i] = nums1[i]; } for (int i = nums1.length; i < res.length; i++){ res[i] = nums2[n]; n++; } Arrays.sort(res); if(len % 2 == 0){ return (double)(res[len/2] + res[len/2 - 1])/2; }else{ return res[len/2]; } } }
問題:
- 拷貝產生新的陣列從而增加時間複雜度,而題目限制了時間複雜度為 O(log (m+n)),沒達到要求。
2.二分法
用到二分的方法才能達到 O(log(m+n))
分別找第 (m+n+1) / 2 個,和 (m+n+2) / 2 個,然後求其平均值即可,對奇偶數均適用。
由於數列是有序的,其實我們完全可以一半兒一半兒的排除。假設我們要找第 k 小數,我們可以每次迴圈排除掉 k/2 個數。
class Solution { public double findMedianSortedArrays(int[] A, int[] B) { int m = A.length; int n = B.length; if (m > n) { return findMedianSortedArrays(B,A); // 保證 m <= n } int iMin = 0, iMax = m; while (iMin <= iMax) { int i = (iMin + iMax) / 2; int j = (m + n + 1) / 2 - i; if (j != 0 && i != m && B[j-1] > A[i]){ // i 需要增大 iMin = i + 1; } else if (i != 0 && j != n && A[i-1] > B[j]) { // i 需要減小 iMax = i - 1; } else { // 達到要求,並且將邊界條件列出來單獨考慮 int maxLeft = 0; if (i == 0) { maxLeft = B[j-1]; } else if (j == 0) { maxLeft = A[i-1]; } else { maxLeft = Math.max(A[i-1], B[j-1]); } if ( (m + n) % 2 == 1 ) { return maxLeft; } // 奇數的話不需要考慮右半部分 int minRight = 0; if (i == m) { minRight = B[j]; } else if (j == n) { minRight = A[i]; } else { minRight = Math.min(B[j], A[i]); } return (maxLeft + minRight) / 2.0; //如果是偶數的話返回結果 } } return 0.0; } }