leetcode 4 :寻找两个正序数组的中位数
1. 题目
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。
请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
2. 示例:
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
3. 自己的解决方法
主要用到快速排序,进行排序,然后找中位数
快速排序
-
通过一趟排序将要排序的数据分割成独立的两部分,
其中一部分的所有数据都比另外一部分的所有数据都要小,
然后递归进行,以此达到整个数据变成有序序列。 -
思想:找出一个基准 pivot 然后把数据分成两部分 然后再递归
-
时间复杂度:平均O(nlog(n)),最坏:O(n^2))
空间复杂度:O(log(n))
是否稳定:不稳定/* 快速排序处理 */ void mySwap(int *i, int *j) { int tmp = *i; *i = *j; *j = tmp; } int partion(int arr[], int low, int high) { int pivot = arr[low]; while (low < high) { while (low < high && arr[high] >= pivot) { high--; } mySwap(&arr[low], &arr[high]); while (low < high && arr[low] <= pivot) { low++; } mySwap(&arr[low], &arr[high]); } return low; } void q_sort(int arr[], int low, int high) { if (low < high) { int pivot = partion(arr, low, high); q_sort(arr, low, pivot - 1); q_sort(arr, pivot + 1, high); } } void quick_sort(int arr[], int len) { q_sort(arr, 0, len - 1); } /* 寻找中位数 */ double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) { int iAllSize = nums1Size + nums2Size; /* 判断是否都为空 */ if(0 == iAllSize) { return 0; } int aiAllArr[iAllSize]; memset(aiAllArr, 0, iAllSize); int iLoop = 0; int iLoop2 = 0; /* 如果一个数组为空的处理 */ if(0 == nums1Size) { if(0 == nums2Size) { return 0; } if(0 == nums2Size%2) { return (double)(nums2[nums2Size/2] + nums2[nums2Size/2 - 1])/2; }else { return (double)nums2[nums2Size/2]; } } /* 如果一个数组为空的处理 */ if(0 == nums2Size) { if(0 == nums1Size) { return 0; } if(0 == nums1Size%2) { return (double)(nums1[nums1Size/2] + nums1[nums1Size/2 - 1])/2; }else { return (double)nums1[nums1Size/2]; } } /* 两个数组合并成一个数组处理 */ for(iLoop = 0; iLoop < nums1Size; iLoop ++) { aiAllArr[iLoop] = nums1[iLoop]; } for(iLoop2 = 0 ;iLoop2 < nums2Size; iLoop2 ++) { aiAllArr[iLoop] = nums2[iLoop2]; iLoop ++; } /* 对总的数组快速排序 */ quick_sort(aiAllArr, iAllSize); /* 找出中位数 */ if(0 == iAllSize%2) { return (double)(aiAllArr[iAllSize/2] + aiAllArr[iAllSize/2 - 1])/2; }else { return (double)aiAllArr[iAllSize/2]; } }
4. 标准答案
#include <stdio.h>
#include <vector>
using namespace std;
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
int m = nums2.size();
if (n > m) //保证数组1一定最短
{
return findMedianSortedArrays(nums2, nums1);
}
// Ci 为第i个数组的割,比如C1为2时表示第1个数组只有2个元素。LMaxi为第i个数组割后的左元素。RMini为第i个数组割后的右元素。
int LMax1, LMax2, RMin1, RMin2, c1, c2, lo = 0, hi = 2 * n; //我们目前是虚拟加了'#'所以数组1是2*n长度
while (lo <= hi) //二分
{
c1 = (lo + hi) / 2; //c1是二分的结果
c2 = m + n - c1;
LMax1 = (c1 == 0) ? INT_MIN : nums1[(c1 - 1) / 2];
RMin1 = (c1 == 2 * n) ? INT_MAX : nums1[c1 / 2];
LMax2 = (c2 == 0) ? INT_MIN : nums2[(c2 - 1) / 2];
RMin2 = (c2 == 2 * m) ? INT_MAX : nums2[c2 / 2];
if (LMax1 > RMin2)
hi = c1 - 1;
else if (LMax2 > RMin1)
lo = c1 + 1;
else
break;
}
return (max(LMax1, LMax2) + min(RMin1, RMin2)) / 2.0;
}
};
int main(int argc, char *argv[])
{
vector<int> nums1 = { 2,3, 5 };
vector<int> nums2 = { 1,4,7, 9 };
Solution solution;
double ret = solution.findMedianSortedArrays(nums1, nums2);
return 0;
}