生活随笔
收集整理的這篇文章主要介紹了
LeetCode 4. 寻找两个有序数组的中位数(二分查找,难)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1. 題目
- 2. 解題
- 2.1 合并數組
- 2.2 優化2.1解法,雙指針
- 2.3 二分法(找第k個數)
- 2.4 切分法
1. 題目
給定兩個大小為 m 和 n 的有序數組 nums1 和 nums2。
請你找出這兩個有序數組的中位數,并且要求算法的時間復雜度為O(log(m+n))O(log(m + n))O(log(m+n))。
你可以假設 nums1 和 nums2 不會同時為空。
示例
1:
nums1
= [1, 3]
nums2
= [2]
則中位數是
2.0示例
2:
nums1
= [1, 2]
nums2
= [3, 4]
則中位數是
(2 + 3)/2 = 2.5
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。
2. 解題
2.1 合并數組
- 合并兩個數組,再取中位數
- 時間和空間復雜度均為 O(m+n)
class Solution {
public:double findMedianSortedArrays(vector
<int>& nums1
, vector
<int>& nums2
) {int n1
= nums1
.size(), n2
= nums2
.size(), len
;len
= n1
+ n2
;vector
<int> nv(len
);int i
= 0, j
= 0, k
= 0;while(i
< n1
&& j
< n2
){if(nums1
[i
] < nums2
[j
])nv
[k
++] = nums1
[i
++];elsenv
[k
++] = nums2
[j
++];}if(i
== n1
){while(j
< n2
)nv
[k
++] = nums2
[j
++];}else{while(i
< n1
)nv
[k
++] = nums1
[i
++];}if(len
%2)return nv
[len
/2];return (nv
[len
/2]+nv
[len
/2-1])/2.0;}
};
2.2 優化2.1解法,雙指針
- 不合并兩個數組,設置雙指針在兩個數組上
- 比較大小,分別移動各自的指針,遍歷到中間的計數停止
- 時間復雜度 O(m+n),空間復雜度 O(1)
class Solution {
public:double findMedianSortedArrays(vector
<int>& nums1
, vector
<int>& nums2
) {int n1
= nums1
.size(), n2
= nums2
.size(), len
;len
= n1
+ n2
;vector
<int> nv(len
);int i
= 0, j
= 0, k
, left
= -1, right
= -1;for(k
= 0; k
<= len
/2; ++k
){left
= right
;if(i
< n1
&& (j
>= n2
|| nums1
[i
] < nums2
[j
]))right
= nums1
[i
++];elseright
= nums2
[j
++];}if(len
%2)return right
;return (left
+right
)/2.0; }
};
2.3 二分法(找第k個數)
參考鏈接,解法3
class Solution {
public:double findMedianSortedArrays(vector
<int>& nums1
, vector
<int>& nums2
) {int n1
= nums1
.size(), n2
= nums2
.size(), len
, kth
;len
= n1
+ n2
;kth
= (len
+1)/2;if(len
%2)return findKth(nums1
,0,n1
-1,nums2
,0,n2
-1,kth
);return (findKth(nums1
,0,n1
-1,nums2
,0,n2
-1,kth
)+findKth(nums1
,0,n1
-1,nums2
,0,n2
-1,kth
+1))/2.0; }int findKth(vector
<int>& nums1
, int s1
, int e1
, vector
<int>& nums2
, int s2
, int e2
, int kth
){int len1
= e1
-s1
+1;int len2
= e2
-s2
+1;if(len1
> len2
) return findKth(nums2
,s2
,e2
,nums1
,s1
,e1
,kth
);if(len1
== 0)return nums2
[s2
+kth
-1];if(kth
== 1)return min(nums1
[s1
],nums2
[s2
]);int i
= s1
+min(len1
,kth
/2)-1;int j
= s2
+min(len2
,kth
/2)-1;if(nums1
[i
] > nums2
[j
])return findKth(nums1
,s1
,e1
,nums2
,j
+1,e2
,kth
-(j
-s2
+1));elsereturn findKth(nums1
,i
+1,e1
,nums2
,s2
,e2
,kth
-(i
-s1
+1));}
};
O(lg(m+n))O(lg(m+n))O(lg(m+n))時間復雜度,尾遞歸,無需堆棧,空間復雜度 O(1)O(1)O(1)
2.4 切分法
- 放了方便處理,確保A數組長度較短
- 初始狀態下mid1取數組1的中間,mid1,mid2左半邊的總個數 == 右半邊 或者 比右半邊少1
- 對mid1進行二分查找,相應的mid2會隨動(mid2=allHalf?mid1mid2 = allHalf - mid1mid2=allHalf?mid1)
- 如果 lmax1<=rmin2,andlmax2<=rmin1lmax1 <= rmin2 ,\quad and \quad lmax2 <= rmin1lmax1<=rmin2,andlmax2<=rmin1 , 成功找到分界線
- 則 Lmax=max(lmax1,lmax2))Lmax = max(lmax1,lmax2))Lmax=max(lmax1,lmax2)), Rmin=min(rmin1,rmin2)Rmin = min(rmin1, rmin2)Rmin=min(rmin1,rmin2),總個數為奇數返回RminRminRmin, 偶數返回(Lmax+Rmin)/2.0(Lmax+Rmin)/2.0(Lmax+Rmin)/2.0
class Solution {
public:double findMedianSortedArrays(vector
<int>& nums1
, vector
<int>& nums2
) {int n1
= nums1
.size(), n2
= nums2
.size();if(n1
> n2
)return findMedianSortedArrays(nums2
, nums1
);int left
= 0, right
= n1
, allHalf
= (n1
+n2
)/2, mid1
, mid2
;int lmax1
, rmin1
, lmax2
, rmin2
;while(left
<= right
){mid1
= left
+((right
-left
)>>1);mid2
= allHalf
- mid1
;lmax1
= (mid1
-1 >= 0) ? nums1
[mid1
-1] : INT_MIN
;rmin1
= (mid1
< n1
) ? nums1
[mid1
] : INT_MAX
;lmax2
= (mid2
-1 >= 0) ? nums2
[mid2
-1] : INT_MIN
;rmin2
= (mid2
< n2
) ? nums2
[mid2
] : INT_MAX
;if(lmax1
> rmin2
)right
= mid1
-1;else if(lmax2
> rmin1
)left
= mid1
+1;else{left
= right
= mid1
;break;}}int i
= left
, j
= allHalf
-left
;int l
= max(i
-1 >= 0 ? nums1
[i
-1] : INT_MIN
,j
-1 >= 0 ? nums2
[j
-1] : INT_MIN
);int r
= min(i
< n1
? nums1
[i
] : INT_MAX
,j
< n2
? nums2
[j
] : INT_MAX
);if((n1
+n2
)%2 == 1)return r
;return (l
+r
)/2.0;}
};
總結
以上是生活随笔為你收集整理的LeetCode 4. 寻找两个有序数组的中位数(二分查找,难)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。