【算法題】兩有序數組中位數

有兩個排序的數組,長度都爲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;

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