Leetcode 4 尋找兩個正序數組的中位數 C++解法思路

題目

在這裏插入圖片描述

思路代碼

這道題讓我們求兩個有序數組的中位數,而且限制了時間複雜度爲O(log (m+n)),看到這個時間複雜度,自然而然的想到了應該使用二分查找法來求解。那麼回顧一下中位數的定義,如果某個有序數組長度是奇數,那麼其中位數就是最中間那個,如果是偶數,那麼就是最中間兩個數字的平均值。這裏對於兩個有序數組也是一樣的,假設兩個有序數組的長度分別爲m和n,由於兩個數組長度之和 m+n 的奇偶不確定,因此需要分情況來討論,對於奇數的情況,直接找到最中間的數即可,偶數的話需要求最中間兩個數的平均值。爲了簡化代碼,不分情況討論,我們使用一個小trick,我們分別找第 (m+n+1) / 2 個,和 (m+n+2) / 2 個,然後求其平均值即可,這對奇偶數均適用。加入 m+n 爲奇數的話,那麼其實 (m+n+1) / 2 和 (m+n+2) / 2 的值相等,相當於兩個相同的數字相加再除以2,還是其本身。

這裏我們需要定義一個函數來在兩個有序數組中找到第K個元素,下面重點來看如何實現找到第K個元素。首先,爲了避免產生新的數組從而增加時間複雜度,我們使用兩個變量i和j分別來標記數組nums1和nums2的起始位置。

  1. 比如當某一個數組的起始位置大於等於其數組長度時,說明其所有數字均已經被淘汰了,相當於一個空數組了,那麼實際上就變成了在另一個數組中找數字,直接就可以找出來了。
  2. 還有就是如果K=1的話,那麼我們只要比較nums1和nums2的起始位置i和j上的數字就可以了。
  3. 難點就在於一般的情況怎麼處理?因爲我們需要在兩個有序數組中找到第K個元素,爲了加快搜索的速度,我們要使用二分法,對K二分,意思是我們需要分別在nums1和nums2中查找第K/2個元素,注意這裏由於兩個數組的長度不定,所以有可能某個數組沒有第K/2個數字,所以我們需要先檢查一下,數組中到底存不存在第K/2個數字,如果存在就取出來,否則就賦值上一個整型最大值。如果某個數組沒有第K/2個數字,那麼我們就淘汰另一個數字的前K/2個數字即可。有沒有可能兩個數組都不存在第K/2個數字呢,這道題裏是不可能的,因爲我們的K不是任意給的,而是給的m+n的中間值,所以必定至少會有一個數組是存在第K/2個數字的。最後就是二分法的核心啦,比較這兩個數組的第K/2小的數字midVal1和midVal2的大小,如果第一個數組的第K/2個數字小的話,那麼說明我們要找的數字肯定不在nums1中的前K/2個數字,所以我們可以將其淘汰,將nums1的起始位置向後移動K/2個,並且此時的K也自減去K/2,調用遞歸。反之,我們淘汰nums2中的前K/2個數字,並將nums2的起始位置向後移動K/2個,並且此時的K也自減去K/2,調用遞歸即可。
class Solution {
    int len1;
    int len2;
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        if(nums1.size()<=0 && nums2.size()<=0)
            return 0;
        len1 = nums1.size();
        len2 = nums2.size();
        int left = (len1+len2+1)/2,right = (len1+len2+2)/2;
        return (find(nums1,0,nums2,0,left) +  find(nums1,0,nums2,0,right) )/2.0;
    }
    
    int find(vector<int>& nums1,int i,vector<int>& nums2,int j,int k) //i,j代表索引(0開始),k代表第幾個數(1開始)
    {
        if(i>=nums1.size()) return nums2[j+k-1];   //對應情況1
        if(j>=nums2.size()) return nums1[i+k-1];	//對應情況1
        if(k == 1)		//對應情況2
            return min(nums1[i],nums2[j]);
        int midval1 = i+k/2-1 < nums1.size()?nums1[i+k/2-1]:INT_MAX;  //以下是情況3
        int midval2 = j+k/2-1 < nums2.size()?nums2[j+k/2-1]:INT_MAX;
        if(midval1<midval2)
            return find(nums1,i+k/2,nums2,j,k-k/2);
        else
            return find(nums1,i,nums2,j+k/2,k-k/2);

在這裏插入圖片描述

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