0.问题描述
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。
请找出这两个有序数组的中位数。要求算法的时间复杂度为 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
1.问题分析
难度为difficult的题出人意料的AC了!
题目是给了两个已知顺序的数组,这点很关键。要求中位数。vector好的一点是内部提供了求长度的函数,如果没有的话其实我们的算法里也可以添加。那么就同时遍历两个数组,将两者比较的较小数压到新的数组中去。最后根据新数组的长度奇偶性分类,奇数就直接取1/2的位置,偶数在进行取平均数运算。
当然了,事后冷静一下眉头一皱发现不简单。这道题的本意似乎不是使用这么暴力的解法,应当是使用折半查找的策略进行计算。
2.C++代码
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
vector<int> nums;
int i = 0, j = 0;
while (i <= nums1.size() && j <= nums2.size()) {
if (nums1[i] < nums2[j]) {
nums.push_back(nums1[i]);
i++;
continue;
}
else {
nums.push_back(nums2[j]);
j++;
continue;
}
}
if (i < nums1.size()) {
for (; i < nums1.size(); i++) {
nums.push_back(nums1[i]);
}
}
if (j < nums2.size()) {
for (; j < nums2.size(); j++) {
nums.push_back(nums2[j]);
}
}
double res;
int len = nums.size();
if (len % 2) {
res = nums[len / 2 + 1];
}
else {
res = (nums[len / 2] + nums[len / 2 + 1]) / 2;
}
return res;
}
};
要注意的是,最后取中位数位置时,直接除以2就是中位数的位置,不用加1,因为数组是从0开始计算的。
并且这个方法的复杂度是O(m+n)emmm
3.C++折半查找
最好的方法是这个,时间的复杂度为O(log(m+n))。采用折半查找的方法。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m, n;
double result;
vector<int> A,B;
if (nums1.size() <= nums2.size()) {
A = nums1;
B = nums2;
m = nums1.size();
n = nums2.size();
}
else {
A = nums2;
B = nums1;
m = nums2.size();
n = nums1.size();
}
if (m == 0) {
if (n % 2) {
return B[n/2];
}
else {
return (B[n/2-1] + B[n/2])/2.0;
}
}
int i = 0;
int j = (m + n + 1)/2 - i;
if (B[j-1] <= A[i] && j != n) {
if ((m + n) % 2) {
result = B[j-1];
return result;
}
else {
result = A[i] < B[j] ? (A[i] + B[j-1])/2.0 : (B[j] + B[j-1])/2.0;
return result;
}
}
else if (B[j-1] <= A[i]) {
if ((m + n) % 2) {
result = B[j-1];
return result;
}
else {
result = (A[i] + B[j-1])/2.0;
return result;
}
}
i = m;
j = (m + n + 1)/2 - i;
if (A[i-1] <= B[j] && j != 0) {
if ((m + n) % 2) {
result = A[i-1] > B[j-1] ? A[i-1] : B[j-1];
return result;
}
else {
result = A[i-1] > B[j-1] ? (A[i-1] + B[j])/2.0 : (B[j-1] + B[j])/2.0;
return result;
}
}
else if (A[i-1] <= B[j]) {
if ((m + n) % 2) {
result = A[i-1];
return result;
}
else {
result = (A[i-1] + B[j])/2.0;
return result;
}
}
//折半查找
int sta = 1,end = m - 1;
while (sta <= end) {
i = (sta + end)/2;
j = (m + n + 1)/2 - i;
if (A[i -1] > B[j]) {
end = i - 1;
}
else if (B[j-1] > A[i]) {
sta = i + 1;
}
else {
break;
}
}
if ((m + n) % 2) {
result = A[i-1] > B[j-1] ? A[i-1] : B[j-1];
return result;
}
else {
int fmax = A[i-1] > B[j-1] ? A[i-1] : B[j-1];
int lmin = A[i] < B[j] ? A[i] : B[j];
result = (fmax + lmin)/2.0;
return result;
}
}
};
4.Java解法
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n1 = nums1.length;
int n2 = nums2.length;
if (n1>n2)
return findMedianSortedArrays(nums2, nums1);
int k = (n1 + n2 + 1)/2;
int left = 0;
int right = n1;
while(left < right){
int m1 = left +(right - left)/2;
int m2 = k - m1;
if (nums1[m1] < nums2[m2-1])
left = m1 + 1;
else
right = m1;
}
int m1 = left;
int m2 = k - left;
int c1 = Math.max(m1 <= 0 ? Integer.MIN_VALUE : nums1[m1-1],
m2 <= 0 ? Integer.MIN_VALUE : nums2[m2-1]);
if ((n1 + n2) % 2 == 1)
return c1;
int c2 = Math.min( m1 >= n1 ? Integer.MAX_VALUE :nums1[m1],
m2 >= n2 ? Integer.MAX_VALUE : nums2[m2]);
return (c1 + c2) * 0.5;
}
}
5.Python解法
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
l1=len(nums1)
l2=len(nums2)
l=l1+l2
if l==0:
return None
if l==1:
if nums1:
return nums1[-1]
if nums2:
return nums2[-1]
num=[]
i=j=0
while i<len(nums1) and j<len(nums2):
if nums1[i]>nums2[j]:
num.append(nums2[j])
j+=1
elif nums1[i]<nums2[j]:
num.append(nums1[i])
i+=1
else:
num.append(nums1[i])
num.append(nums2[j])
i+=1
j+=1
while i<len(nums1):
num.append(nums1[i])
i+=1
while j<len(nums2):
num.append(nums2[j])
j+=1
if l%2==0:
return float((num[l//2-1]+num[l//2])/2)
else:
return float(num[l//2])
使用折半查找的Python算法:
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
n1 = len(nums1)
n2 = len(nums2)
if n1 > n2:
return self.findMedianSortedArrays(nums2,nums1)
k = (n1 + n2 + 1)//2
left = 0
right = n1
while left < right :
m1 = left +(right - left)//2
m2 = k - m1
if nums1[m1] < nums2[m2-1]:
left = m1 + 1
else:
right = m1
m1 = left
m2 = k - m1
c1 = max(nums1[m1-1] if m1 > 0 else float("-inf"), nums2[m2-1] if m2 > 0 else float("-inf") )
if (n1 + n2) % 2 == 1:
return c1
c2 = min(nums1[m1] if m1 < n1 else float("inf"), nums2[m2] if m2 <n2 else float("inf"))
return (c1 + c2) / 2