【算法题】两有序数组中位数

有两个排序的数组,长度都为n,求合并后的排序数组的中位数。要求时间复杂度为log(n)。


解法1:直接的解法是遍历两个数组并计数,类似归并排序里面的有序数组的合并,复杂度为O(n)


解法2:分治策略

设两个数组为A[n],B[n]。

若A[n/2] < B[n/2]:中位数k必定位于A[n/2]-A[n]、B[0]-B[n/2]。且k也是两个数组A[n/2]-A[n]、B[0]-B[n/2]的中位数。

若A[n/2] > B[n/2]:中位数k必定位于A[0]-A[n/2]、B[n/2]-B[n]。且k也是两个数组A[0]-A[n/2]、B[n/2]-B[n]的中位数。

若A[n/2] == B[n/2],则A[n/2]为中位数。
若数组无法细分下去,则可直接计算中位数。


设A[i],B[j]为中位数k,则i+j = n;

若A[n/2] < B[n/2]:则 (i-n/2)+j = n/2;
k还是两个数组A[n/2]-A[n]、B[0]-B[n/2]的中位数。


时间复杂度:

Tn=Tn/2+f(n)

f(n)=O(1)=O(nlog21)

T(n)=O(nlog21log(n))=O(log(n))


#include <stdio.h>
#include <vector>
#include <numeric>
#include <algorithm>
#include <iostream>
using namespace std;
#define debug_

double find_mid_core(vector<int>& nums1, vector<int>& nums2, int left_1, int right_1, int left_2, int right_2)
{
    if (right_1 ==  left_1+1)
    {
        return (double)(max(nums1[left_1], nums2[left_2]) + min(nums1[right_1], nums2[right_2]))/2.0;
    }
    int mid_1 = left_1 + ((right_1 - left_1) >> 1);
    int mid_2 = left_2 + ((right_2 - left_2) >> 1);

    if (nums1[mid_1] > nums2[mid_2])
    {
        return find_mid_core(nums1, nums2, left_1, mid_1, mid_2, right_2);
    }
    else if (nums1[mid_1] < nums2[mid_2])
    {
        return find_mid_core(nums1, nums2, mid_1, right_1, left_2, mid_2);
    }
    else
    {
        return nums1[mid_1];
    }
}

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2)
{
    int left_1 = 0;
    int right_1 = nums1.size() - 1;
    int left_2 = 0;
    int right_2 = nums2.size() - 1;
    return find_mid_core(nums1, nums2, left_1, right_1, left_2, right_2);
}

int main()
{
    vector<int> vec_1{ 1, 12, 15, 26, 38 };
    vector<int> vec_2{ 2, 13, 17, 30, 45 };
    cout<<findMedianSortedArrays(vec_1, vec_2);

    return 0;

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章