網站域名登陸長沙seo優(yōu)化價格
文章目錄
- 題目
- 標題和出處
- 難度
- 題目描述
- 要求
- 示例
- 數據范圍
- 解法一
- 思路和算法
- 代碼
- 復雜度分析
- 解法二
- 思路和算法
- 代碼
- 復雜度分析
題目
標題和出處
標題:尋找兩個正序數組的中位數
出處:4. 尋找兩個正序數組的中位數
難度
8 級
題目描述
要求
給定兩個大小分別為 m \texttt{m} m 和 n \texttt{n} n 的升序數組 nums1 \texttt{nums1} nums1 和 nums2 \texttt{nums2} nums2,返回這兩個升序數組的中位數。
要求時間復雜度是 O(log (m + n)) \texttt{O(log (m + n))} O(log?(m?+?n))。
示例
示例 1:
輸入: nums1 = [1,3], nums2 = [2] \texttt{nums1 = [1,3], nums2 = [2]} nums1?=?[1,3],?nums2?=?[2]
輸出: 2.00000 \texttt{2.00000} 2.00000
解釋:合并數組是 [1,2,3] \texttt{[1,2,3]} [1,2,3],中位數是 2 \texttt{2} 2。
示例 2:
輸入: nums1 = [1,2], nums2 = [3,4] \texttt{nums1 = [1,2], nums2 = [3,4]} nums1?=?[1,2],?nums2?=?[3,4]
輸出: 2.50000 \texttt{2.50000} 2.50000
解釋:合并數組是 [1,2,3,4] \texttt{[1,2,3,4]} [1,2,3,4],中位數是 2 + 3 2 = 2.5 \dfrac{\texttt{2} + \texttt{3}}{\texttt{2}} = \texttt{2.5} 22+3?=2.5。
數據范圍
- nums1.length = m \texttt{nums1.length} = \texttt{m} nums1.length=m
- nums2.length = n \texttt{nums2.length} = \texttt{n} nums2.length=n
- 0 ≤ m ≤ 1000 \texttt{0} \le \texttt{m} \le \texttt{1000} 0≤m≤1000
- 0 ≤ n ≤ 1000 \texttt{0} \le \texttt{n} \le \texttt{1000} 0≤n≤1000
- 1 ≤ m + n ≤ 2000 \texttt{1} \le \texttt{m} + \texttt{n} \le \texttt{2000} 1≤m+n≤2000
- -10 6 ≤ nums1[i], nums2[i] ≤ 10 6 \texttt{-10}^\texttt{6} \le \texttt{nums1[i], nums2[i]} \le \texttt{10}^\texttt{6} -106≤nums1[i],?nums2[i]≤106
解法一
思路和算法
已知兩個升序數組的長度分別是 m m m 和 n n n。計算兩個升序數組的中位數可以轉換成找到兩個升序數組的所有元素中的第 k k k 小元素,其中 0 ≤ k < m + n 0 \le k < m + n 0≤k<m+n。用 total = m + n \textit{total} = m + n total=m+n 表示兩個升序數組的長度之和。當 total \textit{total} total 是奇數時, k = total ? 1 2 k = \dfrac{\textit{total} - 1}{2} k=2total?1?,第 k k k 小元素即為中位數;當 total \textit{total} total 是偶數時,分別取 k = total 2 ? 1 k = \dfrac{\textit{total}}{2} - 1 k=2total??1 和 k = total 2 k = \dfrac{\textit{total}}{2} k=2total?,兩次第 k k k 小元素的平均數即為中位數。因此,根據兩個升序數組的長度之和是奇數或偶數,執(zhí)行一次或兩次尋找第 k k k 小元素的操作,即可得到中位數。
由于題目要求時間復雜度是 O ( log ? ( m + n ) ) O(\log (m + n)) O(log(m+n)),因此要求每次尋找第 k k k 小元素的操作的時間復雜度是 O ( log ? ( m + n ) ) O(\log (m + n)) O(log(m+n))。需要使用二分查找實現。
用 k k k 表示目標值在剩余元素中的序號( k k k 從 0 0 0 開始,序號為 k k k 表示剩余元素中有 k k k 個元素小于等于目標值),用 index 1 \textit{index}_1 index1? 和 index 2 \textit{index}_2 index2? 分別表示數組 nums 1 \textit{nums}_1 nums1? 和 nums 2 \textit{nums}_2 nums2? 的首個剩余元素的下標,初始時 index 1 \textit{index}_1 index1? 和 index 2 \textit{index}_2 index2? 都等于 0 0 0。剩余元素表示可能是目標值的元素,查找過程中將不可能是目標值的元素排除。
每次查找時,分別考慮兩個數組的剩余元素中最小的 ? k 2 ? \Big\lceil \dfrac{k}{2} \Big\rceil ?2k?? 個元素,共考慮 k + 1 k + 1 k+1 個元素(當 k k k 是奇數時)或 k k k 個元素(當 k k k 是偶數時),這些元素在兩個數組中的下標范圍分別是 nums 1 \textit{nums}_1 nums1? 的下標范圍 [ index 1 , endIndex 1 ] [\textit{index}_1, \textit{endIndex}_1] [index1?,endIndex1?] 和 nums 2 \textit{nums}_2 nums2? 的下標范圍 [ index 2 , endIndex 2 ] [\textit{index}_2, \textit{endIndex}_2] [index2?,endIndex2?],其中 endIndex 1 = index 1 + ? k ? 1 2 ? \textit{endIndex}_1 = \textit{index}_1 + \Big\lfloor \dfrac{k - 1}{2} \Big\rfloor endIndex1?=index1?+?2k?1??, endIndex 2 = index 2 + ? k ? 1 2 ? \textit{endIndex}_2 = \textit{index}_2 + \Big\lfloor \dfrac{k - 1}{2} \Big\rfloor endIndex2?=index2?+?2k?1??。考慮 nums 1 [ endIndex 1 ] \textit{nums}_1[\textit{endIndex}_1] nums1?[endIndex1?] 和 nums 2 [ endIndex 2 ] \textit{nums}_2[\textit{endIndex}_2] nums2?[endIndex2?],其中的較大值是第 k k k 小元素(當 k k k 是奇數時)或第 k ? 1 k - 1 k?1 小元素(當 k k k 是偶數時),因此其中的較小值一定不是第 k k k 小元素。對于較小值所在的數組,可以將較小值以及較小值前面的元素全部排除。
需要注意的是, endIndex 1 \textit{endIndex}_1 endIndex1? 和 endIndex 2 \textit{endIndex}_2 endIndex2? 不能超出數組下標范圍。如果一個數組的剩余元素個數少于 ? k 2 ? \Big\lceil \dfrac{k}{2} \Big\rceil ?2k??,則該數組中考慮的元素是該數組中的全部剩余元素。因此有 endIndex 1 = min ? ( index 1 + ? k ? 1 2 ? , m ? 1 ) \textit{endIndex}_1 = \min(\textit{index}_1 + \Big\lfloor \dfrac{k - 1}{2} \Big\rfloor, m - 1) endIndex1?=min(index1?+?2k?1??,m?1), endIndex 2 = min ? ( index 2 + ? k ? 1 2 ? , n ? 1 ) \textit{endIndex}_2 = \min(\textit{index}_2 + \Big\lfloor \dfrac{k - 1}{2} \Big\rfloor, n - 1) endIndex2?=min(index2?+?2k?1??,n?1)。
由此可以根據三種情況分別做相應的處理,縮小查找范圍。
-
如果 nums 1 [ endIndex 1 ] < nums 2 [ endIndex 2 ] \textit{nums}_1[\textit{endIndex}_1] < \textit{nums}_2[\textit{endIndex}_2] nums1?[endIndex1?]<nums2?[endIndex2?],則將 nums 1 \textit{nums}_1 nums1? 的下標范圍 [ index 1 , endIndex 1 ] [\textit{index}_1, \textit{endIndex}_1] [index1?,endIndex1?] 中的元素全部排除,排除的元素個數是 endIndex 1 ? index 1 + 1 \textit{endIndex}_1 - \textit{index}_1 + 1 endIndex1??index1?+1。
-
如果 nums 1 [ endIndex 1 ] > nums 2 [ endIndex 2 ] \textit{nums}_1[\textit{endIndex}_1] > \textit{nums}_2[\textit{endIndex}_2] nums1?[endIndex1?]>nums2?[endIndex2?],則將 nums 2 \textit{nums}_2 nums2? 的下標范圍 [ index 2 , endIndex 2 ] [\textit{index}_2, \textit{endIndex}_2] [index2?,endIndex2?] 中的元素全部排除,排除的元素個數是 endIndex 2 ? index 2 + 1 \textit{endIndex}_2 - \textit{index}_2 + 1 endIndex2??index2?+1。
-
如果 nums 1 [ endIndex 1 ] = nums 2 [ endIndex 2 ] \textit{nums}_1[\textit{endIndex}_1] = \textit{nums}_2[\textit{endIndex}_2] nums1?[endIndex1?]=nums2?[endIndex2?],則處理方式和 nums 1 [ endIndex 1 ] < nums 2 [ endIndex 2 ] \textit{nums}_1[\textit{endIndex}_1] < \textit{nums}_2[\textit{endIndex}_2] nums1?[endIndex1?]<nums2?[endIndex2?] 相同。
每次查找之后,將 k k k 的值減去排除的元素個數,并將排除元素的數組的相應下標更新為該數組首個剩余元素的下標,具體做法如下:如果排除的是 nums 1 \textit{nums}_1 nums1? 中的元素,則將 index 1 \textit{index}_1 index1? 更新為 endIndex 1 + 1 \textit{endIndex}_1 + 1 endIndex1?+1;如果排除的是 nums 2 \textit{nums}_2 nums2? 中的元素,則將 index 2 \textit{index}_2 index2? 更新為 endIndex 2 + 1 \textit{endIndex}_2 + 1 endIndex2?+1。
二分查找的條件是 index 1 < m \textit{index}_1 < m index1?<m, index 2 < n \textit{index}_2 < n index2?<n 和 k > 0 k > 0 k>0。如果三個條件之一不滿足,則二分查找結束,得到目標值。
-
如果 index 1 = m \textit{index}_1 = m index1?=m,則剩余元素都在 nums 2 \textit{nums}_2 nums2? 中,目標值是 nums 2 [ index 2 + k ] \textit{nums}_2[\textit{index}_2 + k] nums2?[index2?+k]。
-
如果 index 2 = n \textit{index}_2 = n index2?=n,則剩余元素都在 nums 1 \textit{nums}_1 nums1? 中,目標值是 nums 1 [ index 1 + k ] \textit{nums}_1[\textit{index}_1 + k] nums1?[index1?+k]。
-
如果 k = 0 k = 0 k=0,則剩余元素中的最小元素是目標值,目標值是 min ? ( nums 1 [ index 1 ] , nums 2 [ index 2 ] ) \min(\textit{nums}_1[\textit{index}_1], \textit{nums}_2[\textit{index}_2]) min(nums1?[index1?],nums2?[index2?])。
以下用一個例子說明該解法。
兩個數組是 nums 1 = [ 1 , 2 , 3 , 4 , 5 ] \textit{nums}_1 = [1, 2, 3, 4, 5] nums1?=[1,2,3,4,5], nums 2 = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ] \textit{nums}_2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] nums2?=[1,2,3,4,5,6,7,8,9,10],兩個數組的長度分別是 m = 5 m = 5 m=5, n = 10 n = 10 n=10,長度之和是 15 15 15, k = 7 k = 7 k=7。初始時, index 1 = 0 \textit{index}_1 = 0 index1?=0, index 2 = 0 \textit{index}_2 = 0 index2?=0。
-
根據 index 1 = 0 \textit{index}_1 = 0 index1?=0, index 2 = 0 \textit{index}_2 = 0 index2?=0 和 k = 7 k = 7 k=7 計算得到 endIndex 1 = 3 \textit{endIndex}_1 = 3 endIndex1?=3, endIndex 2 = 3 \textit{endIndex}_2 = 3 endIndex2?=3。由于 nums 1 [ 3 ] = nums 2 [ 3 ] \textit{nums}_1[3] = \textit{nums}_2[3] nums1?[3]=nums2?[3],因此將 nums 1 \textit{nums}_1 nums1? 的下標范圍 [ 0 , 3 ] [0, 3] [0,3] 排除,排除 4 4 4 個元素,更新得到 k = 3 k = 3 k=3, index 1 = 4 \textit{index}_1 = 4 index1?=4。
-
根據 index 1 = 4 \textit{index}_1 = 4 index1?=4, index 2 = 0 \textit{index}_2 = 0 index2?=0 和 k = 3 k = 3 k=3 計算得到 endIndex 1 = 4 \textit{endIndex}_1 = 4 endIndex1?=4, endIndex 2 = 1 \textit{endIndex}_2 = 1 endIndex2?=1。由于 nums 1 [ 4 ] > nums 2 [ 1 ] \textit{nums}_1[4] > \textit{nums}_2[1] nums1?[4]>nums2?[1],因此將 nums 2 \textit{nums}_2 nums2? 的下標范圍 [ 0 , 1 ] [0, 1] [0,1] 排除,排除 2 2 2 個元素,更新得到 k = 1 k = 1 k=1, index 2 = 2 \textit{index}_2 = 2 index2?=2。
-
根據 index 1 = 4 \textit{index}_1 = 4 index1?=4, index 2 = 2 \textit{index}_2 = 2 index2?=2 和 k = 1 k = 1 k=1 計算得到 endIndex 1 = 4 \textit{endIndex}_1 = 4 endIndex1?=4, endIndex 2 = 2 \textit{endIndex}_2 = 2 endIndex2?=2。由于 nums 1 [ 4 ] > nums 2 [ 2 ] \textit{nums}_1[4] > \textit{nums}_2[2] nums1?[4]>nums2?[2],因此將 nums 2 \textit{nums}_2 nums2? 的下標范圍 [ 2 , 2 ] [2, 2] [2,2] 排除,排除 1 1 1 個元素,更新得到 k = 0 k = 0 k=0, index 2 = 3 \textit{index}_2 = 3 index2?=3。
-
此時 k = 0 k = 0 k=0,二分查找結束, nums 1 [ 4 ] \textit{nums}_1[4] nums1?[4] 和 nums 2 [ 3 ] \textit{nums}_2[3] nums2?[3] 中的較小值 4 4 4 即為目標值。
代碼
class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {int m = nums1.length, n = nums2.length;int total = m + n;if (total % 2 == 1) {int medianIndex = (total - 1) / 2;return findKthSmallest(medianIndex, nums1, nums2);} else {int medianIndex1 = total / 2 - 1, medianIndex2 = total / 2;return (findKthSmallest(medianIndex1, nums1, nums2) + findKthSmallest(medianIndex2, nums1, nums2)) / 2.0;}}public int findKthSmallest(int k, int[] nums1, int[] nums2) {int m = nums1.length, n = nums2.length;int index1 = 0, index2 = 0;while (index1 < m && index2 < n && k > 0) {int endIndex1 = Math.min(index1 + (k - 1) / 2, m - 1);int endIndex2 = Math.min(index2 + (k - 1) / 2, n - 1);int num1 = nums1[endIndex1], num2 = nums2[endIndex2];if (num1 <= num2) {k -= endIndex1 - index1 + 1;index1 = endIndex1 + 1;} else {k -= endIndex2 - index2 + 1;index2 = endIndex2 + 1;}}if (index1 == m) {return nums2[index2 + k];} else if (index2 == n) {return nums1[index1 + k];} else {return Math.min(nums1[index1], nums2[index2]);}}
}
復雜度分析
-
時間復雜度: O ( log ? ( m + n ) ) O(\log (m + n)) O(log(m+n)),其中 m m m 和 n n n 分別是數組 nums 1 \textit{nums}_1 nums1? 和 nums 2 \textit{nums}_2 nums2? 的長度。每次尋找第 k k k 小元素時, k k k 的初始值是 m + n m + n m+n 的一半附近的整數,每次查找將 k k k 的值減小一半,因此時間復雜度是 O ( log ? ( m + n ) ) O(\log (m + n)) O(log(m+n))。
-
空間復雜度: O ( 1 ) O(1) O(1)。
解法二
思路和算法
解法一的時間復雜度是 O ( log ? ( m + n ) ) O(\log (m + n)) O(log(m+n)),該時間復雜度已經很低,但是這道題還存在時間復雜度更低的解法。
為了找到中位數,需要在數組 nums 1 \textit{nums}_1 nums1? 和 nums 2 \textit{nums}_2 nums2? 中分別找到分割點 cut 1 \textit{cut}_1 cut1? 和 cut 2 \textit{cut}_2 cut2?,將每個數組分割成兩個部分。
-
數組 nums 1 \textit{nums}_1 nums1? 被分割成下標范圍 [ 0 , cut 1 ? 1 ] [0, \textit{cut}_1 - 1] [0,cut1??1] 和下標范圍 [ cut 1 , m ? 1 ] [\textit{cut}_1, m - 1] [cut1?,m?1] 兩部分,左邊部分的長度是 cut 1 \textit{cut}_1 cut1?。
-
數組 nums 2 \textit{nums}_2 nums2? 被分割成下標范圍 [ 0 , cut 2 ? 1 ] [0, \textit{cut}_2 - 1] [0,cut2??1] 和下標范圍 [ cut 2 , n ? 1 ] [\textit{cut}_2, n - 1] [cut2?,n?1] 兩部分,左邊部分的長度是 cut 2 \textit{cut}_2 cut2?。
其中, 0 ≤ cut 1 ≤ m 0 \le \textit{cut}_1 \le m 0≤cut1?≤m, 0 ≤ cut 2 ≤ n 0 \le \textit{cut}_2 \le n 0≤cut2?≤n,即每個數組分割成的兩個部分中可以有一個部分為空。
假設 nums 1 [ ? 1 ] = nums 2 [ ? 1 ] = ? ∞ \textit{nums}_1[-1] = \textit{nums}_2[-1] = -\infty nums1?[?1]=nums2?[?1]=?∞, nums 1 [ m ] = nums 2 [ n ] = + ∞ \textit{nums}_1[m] = \textit{nums}_2[n] = +\infty nums1?[m]=nums2?[n]=+∞,分割應滿足以下兩個條件。
-
兩個數組的左邊部分的最大值小于等于兩個數組的右邊部分的最小值, max ? ( nums 1 [ cut 1 ? 1 ] , nums 2 [ cut 2 ? 1 ] ) ≤ min ? ( nums 1 [ cut 1 ] , nums 2 [ cut 2 ] ) \max(\textit{nums}_1[\textit{cut}_1 - 1], \textit{nums}_2[\textit{cut}_2 - 1]) \le \min(\textit{nums}_1[\textit{cut}_1], \textit{nums}_2[\textit{cut}_2]) max(nums1?[cut1??1],nums2?[cut2??1])≤min(nums1?[cut1?],nums2?[cut2?])。
-
兩個數組的左邊部分的長度之和為兩個數組的長度之和的一半向上取整, cut 1 + cut 2 = ? m + n 2 ? \textit{cut}_1 + \textit{cut}_2 = \Big\lceil \dfrac{m + n}{2} \Big\rceil cut1?+cut2?=?2m+n??。
將兩個數組的左邊部分統稱為前半部分,將兩個數組的右邊部分統稱為后半部分,則前半部分的最大值小于等于后半部分的最小值,前半部分的元素個數為兩個數組的長度之和的一半向上取整。
用 total = m + n \textit{total} = m + n total=m+n 表示兩個升序數組的長度之和,用 lowerSize = ? total 2 ? \textit{lowerSize} = \Big\lceil \dfrac{\textit{total}}{2} \Big\rceil lowerSize=?2total?? 表示前半部分的元素個數。當 total \textit{total} total 是奇數時,中位數是前半部分的最大值;當 total \textit{total} total 是偶數時,中位數是前半部分的最大值與后半部分的最小值的平均數。
由于已知 cut 1 + cut 2 = lowerSize \textit{cut}_1 + \textit{cut}_2 = \textit{lowerSize} cut1?+cut2?=lowerSize,因此可以在 nums 1 \textit{nums}_1 nums1? 中尋找 cut 1 \textit{cut}_1 cut1?,當 cut 1 \textit{cut}_1 cut1? 確定之后 cut 2 \textit{cut}_2 cut2? 也可以確定。
尋找 cut 1 \textit{cut}_1 cut1? 可以使用二分查找實現。由于兩個數組都是升序數組, nums 1 [ cut 1 ? 1 ] ≤ nums 1 [ cut 1 ] \textit{nums}_1[\textit{cut}_1 - 1] \le \textit{nums}_1[\textit{cut}_1] nums1?[cut1??1]≤nums1?[cut1?] 和 nums 2 [ cut 2 ? 1 ] ≤ nums 2 [ cut 2 ] \textit{nums}_2[\textit{cut}_2 - 1] \le \textit{nums}_2[\textit{cut}_2] nums2?[cut2??1]≤nums2?[cut2?] 都滿足,因此只需要滿足 nums 1 [ cut 1 ? 1 ] ≤ nums 2 [ cut 2 ] \textit{nums}_1[\textit{cut}_1 - 1] \le \textit{nums}_2[\textit{cut}_2] nums1?[cut1??1]≤nums2?[cut2?] 和 nums 2 [ cut 2 ? 1 ] ≤ nums 1 [ cut 1 ] \textit{nums}_2[\textit{cut}_2 - 1] \le \textit{nums}_1[\textit{cut}_1] nums2?[cut2??1]≤nums1?[cut1?] 即可。二分查找需要查找滿足 nums 1 [ cut 1 ? 1 ] ≤ nums 2 [ cut 2 ] \textit{nums}_1[\textit{cut}_1 - 1] \le \textit{nums}_2[\textit{cut}_2] nums1?[cut1??1]≤nums2?[cut2?] 的最大下標 cut 1 \textit{cut}_1 cut1?。
用 low \textit{low} low 和 high \textit{high} high 分別表示二分查找的下標范圍的下界和上界,初始時 low = 0 \textit{low} = 0 low=0, high = m \textit{high} = m high=m。每次查找時,取 index 1 \textit{index}_1 index1? 為 low \textit{low} low 和 high \textit{high} high 的平均數向上取整,并得到 index 2 = lowerSize ? index 1 \textit{index}_2 = \textit{lowerSize} - \textit{index}_1 index2?=lowerSize?index1?,比較 nums 1 [ index 1 ? 1 ] \textit{nums}_1[\textit{index}_1 - 1] nums1?[index1??1] 和 nums 2 [ index 2 ] \textit{nums}_2[\textit{index}_2] nums2?[index2?] 的大小關系,調整查找的下標范圍。
-
如果 nums 1 [ index 1 ? 1 ] ≤ nums 2 [ index 2 ] \textit{nums}_1[\textit{index}_1 - 1] \le \textit{nums}_2[\textit{index}_2] nums1?[index1??1]≤nums2?[index2?],則 cut 1 ≥ index 1 \textit{cut}_1 \ge \textit{index}_1 cut1?≥index1?,因此在下標范圍 [ index 1 , high ] [\textit{index}_1, \textit{high}] [index1?,high] 中繼續(xù)查找。
-
如果 nums 1 [ index 1 ? 1 ] > nums 2 [ index 2 ] \textit{nums}_1[\textit{index}_1 - 1] > \textit{nums}_2[\textit{index}_2] nums1?[index1??1]>nums2?[index2?],則 cut 1 < index 1 \textit{cut}_1 < \textit{index}_1 cut1?<index1?,因此在下標范圍 [ low , index 1 ? 1 ] [\textit{low}, \textit{index}_1 - 1] [low,index1??1] 中繼續(xù)查找。
當 low = high \textit{low} = \textit{high} low=high 時,查找結束,此時 low \textit{low} low 即為 cut 1 \textit{cut}_1 cut1?。
得到 cut 1 \textit{cut}_1 cut1? 之后即可得到 cut 2 \textit{cut}_2 cut2?, nums 1 [ cut 1 ? 1 ] \textit{nums}_1[\textit{cut}_1 - 1] nums1?[cut1??1] 和 nums 2 [ cut 2 ? 1 ] \textit{nums}_2[\textit{cut}_2 - 1] nums2?[cut2??1] 中的最大值是前半部分的最大值, nums 1 [ cut 1 ] \textit{nums}_1[\textit{cut}_1] nums1?[cut1?] 和 nums 2 [ cut 2 ] \textit{nums}_2[\textit{cut}_2] nums2?[cut2?] 中的最小值是后半部分的最小值。根據前半部分的最大值和后半部分的最小值即可計算中位數。
-
當 total \textit{total} total 是奇數時,中位數是前半部分的最大值。
-
當 total \textit{total} total 是偶數時,中位數是前半部分的最大值與后半部分的最小值的平均數。
該解法的時間復雜度是 O ( log ? m ) O(\log m) O(logm),優(yōu)于解法一的 O ( log ? ( m + n ) ) O(\log (m + n)) O(log(m+n))。
實現方面,由于只需要在一個數組中二分查找,因此可以選擇較短的數組二分查找,時間復雜度是 O ( log ? min ? ( m , n ) ) O(\log \min(m, n)) O(logmin(m,n))。
以下用一個例子說明上述過程。
兩個數組是 nums 1 = [ 1 , 2 , 3 , 4 , 5 ] \textit{nums}_1 = [1, 2, 3, 4, 5] nums1?=[1,2,3,4,5], nums 2 = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ] \textit{nums}_2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] nums2?=[1,2,3,4,5,6,7,8,9,10],兩個數組的長度分別是 m = 5 m = 5 m=5, n = 10 n = 10 n=10,長度之和是 15 15 15,前半部分的元素個數是 8 8 8。初始時, low = 0 \textit{low} = 0 low=0, high = 5 \textit{high} = 5 high=5。
-
根據 low = 0 \textit{low} = 0 low=0 和 high = 5 \textit{high} = 5 high=5 計算得到 index 1 = 3 \textit{index}_1 = 3 index1?=3, index 2 = 5 \textit{index}_2 = 5 index2?=5。由于 nums 1 [ 2 ] ≤ nums 2 [ 5 ] \textit{nums}_1[2] \le \textit{nums}_2[5] nums1?[2]≤nums2?[5],因此將 low \textit{low} low 更新為 3 3 3。
-
根據 low = 3 \textit{low} = 3 low=3 和 high = 5 \textit{high} = 5 high=5 計算得到 index 1 = 4 \textit{index}_1 = 4 index1?=4, index 2 = 4 \textit{index}_2 = 4 index2?=4。由于 nums 1 [ 3 ] ≤ nums 2 [ 4 ] \textit{nums}_1[3] \le \textit{nums}_2[4] nums1?[3]≤nums2?[4],因此將 low \textit{low} low 更新為 4 4 4。
-
根據 low = 4 \textit{low} = 4 low=4 和 high = 5 \textit{high} = 5 high=5 計算得到 index 1 = 5 \textit{index}_1 = 5 index1?=5, index 2 = 3 \textit{index}_2 = 3 index2?=3。由于 nums 1 [ 4 ] > nums 2 [ 3 ] \textit{nums}_1[4] > \textit{nums}_2[3] nums1?[4]>nums2?[3],因此將 high \textit{high} high 更新為 4 4 4。
-
此時 low = high \textit{low} = \textit{high} low=high,二分查找結束。根據 low = 4 \textit{low} = 4 low=4 計算得到 cut 1 = 4 \textit{cut}_1 = 4 cut1?=4, cut 2 = 4 \textit{cut}_2 = 4 cut2?=4,前半部分的最大值是 4 4 4,后半部分的最小值是 5 5 5。由于兩個數組的長度之和是奇數,因此中位數是前半部分的最大值,中位數是 4 4 4。
代碼
class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {return nums1.length <= nums2.length ? findMedian(nums1, nums2) : findMedian(nums2, nums1);}public double findMedian(int[] shorter, int[] longer) {int length1 = shorter.length, length2 = longer.length;int total = length1 + length2;int lowerSize = (total + 1) / 2;int low = 0, high = length1;while (low < high) {int index1 = low + (high - low + 1) / 2;int index2 = lowerSize - index1;int left1 = shorter[index1 - 1];int right2 = longer[index2];if (left1 <= right2) {low = index1;} else {high = index1 - 1;}}int cut1 = low, cut2 = lowerSize - low;int lower1 = cut1 == 0 ? Integer.MIN_VALUE : shorter[cut1 - 1];int lower2 = cut2 == 0 ? Integer.MIN_VALUE : longer[cut2 - 1];int higher1 = cut1 == length1 ? Integer.MAX_VALUE : shorter[cut1];int higher2 = cut2 == length2 ? Integer.MAX_VALUE : longer[cut2];int lowerMax = Math.max(lower1, lower2), higherMin = Math.min(higher1, higher2);if (total % 2 == 1) {return lowerMax;} else {return (lowerMax + higherMin) / 2.0;}}
}
復雜度分析
-
時間復雜度: O ( log ? min ? ( m , n ) ) O(\log \min(m, n)) O(logmin(m,n)),其中 m m m 和 n n n 分別是數組 nums 1 \textit{nums}_1 nums1? 和 nums 2 \textit{nums}_2 nums2? 的長度。在較短的數組中二分查找,范圍是 [ 0 , min ? ( m , n ) ] [0, \min(m, n)] [0,min(m,n)],二分查找的次數是 O ( log ? min ? ( m , n ) ) O(\log \min(m, n)) O(logmin(m,n)),每次查找的時間是 O ( 1 ) O(1) O(1),因此時間復雜度是 O ( log ? min ? ( m , n ) ) O(\log \min(m, n)) O(logmin(m,n))。
-
空間復雜度: O ( 1 ) O(1) O(1)。