題目:
給定兩個大小分別為 m 和 n 的正序(從小到大)數組 nums1 和 nums2。請你找出并返回這兩個正序數組的 中位數 。
算法的時間復雜度應該為 O(log (m+n)) 。
示例:
輸入:nums1 = [1,3], nums2 = [2]
輸出:2.00000
解釋:合并數組 = [1,2,3] ,中位數 2
解題思路:
詳細的題解請參見https://leetcode.cn/problems/median-of-two-sorted-arrays/solutions/2950686/tu-jie-xun-xu-jian-jin-cong-shuang-zhi-z-p2gd
下面是我對題解的一些理解,我使用的是閉區間的寫法:
這道題的難點就在于時間復雜度要求,就限制了不能用遍歷來找到中位數。
中位數也就是有序數組中排在中間位置的數,換句話說中位數把有序數組分成了兩部分,兩部分的元素個數相同(如果數組元素個數是奇數,則讓左邊部分比右邊部分多一個),并且左邊部分的所有元素都比右邊部分的所有元素小(即是左邊部分的最大值都小于右邊部分的最小值)。
既然我們知道了m和n,自然也就知道了左邊部分和右邊部分的元素個數(m + n + 1)/ 2,那么假設左邊部分中的元素是由nums1中的i個元素+nums2中的j個元素組成,且i + j == (m + n + 1)/ 2,所以我們如果知道了i,自然也就知道了j,也就得到了左邊部分的元素和右邊部分的元素,也就是一種劃分情況,枚舉i的個數,也就得到不同的左右部分劃分情況,其中只有一個劃分情況能夠滿足左邊部分的最大值小于右邊部分的最小值,此時也就找到了中位數,如果數組元素個數是奇數,中位數=左邊部分的最大值,如果是偶數,則中位數=(左邊部分最大值 + 右邊部分最小值)/ 2。
滿足條件的劃分是唯一的,并且此時的 i 是滿足nums1[i] <= nums2[j + 1]的最大值,而這個i我們可以通過二分的方法來查找。
class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {// 1、如果nums1的長度大于nums2,則交換if(nums1.length > nums2.length){int[] temp = nums1;nums1 = nums2;nums2 = temp;}// 2、二分尋找最大滿足nums1[i] < nums2[j + 1]int m = nums1.length, n = nums2.length;int left = 0, right = m - 1;while(left <= right){int i = left + (right - left) / 2;int j = (m + n + 1) / 2 - (i + 1) - 1;if(nums1[i] < nums2[j + 1]){left = i + 1;}else{right = i - 1;}}int i = right;int j = (m + n + 1) / 2 - (i + 1) - 1;int ai = i >= 0 ? nums1[i] : Integer.MIN_VALUE;int bj = j >= 0 ? nums2[j] : Integer.MIN_VALUE;int ai1 = (i + 1) < m ? nums1[i + 1] : Integer.MAX_VALUE;int bj1 = (j + 1) < n ? nums2[j + 1] : Integer.MAX_VALUE;int max1 = Math.max(ai, bj);int min2 = Math.min(ai1, bj1);return (m + n) % 2 > 0 ? max1 : (max1 + min2) / 2.0;}
}