4. Median of Two Sorted Arrays

題目描述:給兩個有序數(shù)組,找出這些數(shù)的中位數(shù)评腺。要求復(fù)雜度O(log (m+n))杈女。

分析:一般化的問題是找所有數(shù)中第K大的數(shù)『阑澹可以根據(jù)歸并排序中merge的思路合并兩個數(shù)組在取第K大的值顶捷,復(fù)雜度O(m + n)。方法一在這個思路上改進一點屎篱,不排序而只設(shè)計數(shù)器記下當(dāng)前已找到第x大的數(shù)服赎,復(fù)雜度仍然是O(m + n)葵蒂。方法二根據(jù)排序特性利用二分來解決,每次可刪除k/2的元素重虑,方法三是其非遞歸找中位數(shù)版践付,復(fù)雜度都是O(log (m+n))。

方法一:時空復(fù)雜度都是O(m + n)缺厉,還是可以過OJ永高。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {

        int l1 = nums1.size(), l2 = nums2.size();
        int cnt = l1 + l2, mid = cnt / 2;
        int e = !(cnt % 2);          //設(shè)標(biāo)志總個數(shù)是否為偶數(shù)使兩種情況統(tǒng)一處理,e == 1為偶數(shù)芽死,返回(v[mid] + v[mid - e]) / 2.0; e == 0為奇數(shù)乏梁,返回(v[mid] + v[mid - e]) / 2.0。

        if (l1 == 0) return (nums2[mid] + nums2[mid - e]) / 2.0;
        if (l2 == 0) return (nums1[mid] + nums1[mid - e]) / 2.0;
        
        vector<int> v;
        int i = 0, j = 0, k;
        for (k = 0; k <= mid; k ++)
        {
            //錯誤處1关贵,i >= l可能導(dǎo)致訪問過界遇骑,設(shè)為最大整數(shù)值即可
            int a = i < l1? nums1[i] : INT_MAX;
            int b = j < l2? nums2[j] : INT_MAX;
            if (a < b)
                v.push_back(nums1[i ++]);     //錯誤處2,不能用下標(biāo)v[k++]在尾部追加賦值
            else 
                v.push_back(nums2[j ++]);
        }

        return (v[mid] + v[mid - e]) / 2.0;
    }
};

出現(xiàn)錯誤“reference binding to null pointer of type 'value_type'”的原因見代碼注釋1 揖曾、 2兩處落萎。主要是vector與數(shù)組的區(qū)別,動態(tài)分配內(nèi)存所以不能用下標(biāo)方式追加數(shù)炭剪。

方法二:通用的用分治法找第K大的數(shù)练链。設(shè)l = nums.size()可發(fā)現(xiàn)如下規(guī)律:

  • 若l % 2 == 1,數(shù)組中位數(shù) = 第 (l + 1) / 2 大的數(shù) = 第(l + 2) / 2大數(shù) = (第 (l + 1) / 2 大的數(shù) + 第(l + 2) / 2大數(shù) )/ 2
  • 若l % 2 == 0奴拦,數(shù)組中位數(shù) = (第 (l + 1) / 2 大的數(shù) + 第(l + 2) / 2大數(shù) )/ 2
class Solution {
public:  
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {  
        int l1 = nums1.size(), l2 = nums2.size();
        //調(diào)用查找第K大函數(shù)媒鼓,不是下標(biāo)
        return (findKth(nums1, nums2, (l1 + l2 + 1) / 2) + findKth(nums1, nums2, (l1 + l2 + 2) / 2)) / 2.0;
    }  
    
    int findKth(vector<int> nums1, vector<int> nums2, int k)
    {
        int l1 = nums1.size(), l2 = nums2.size();
        //固定nums1的長度較短,減少判斷情況
        if (l1 > l2) return findKth(nums2, nums1, k);
        if (l1 == 0) return nums2[k - 1];
        if (k == 1) return min(nums1[0], nums2[0]);

        //統(tǒng)一數(shù)組長度小于k / 2的情況错妖。
        int i = min(l1, k/2), j = min(l2, k / 2);
        //nums2的前j - 1(不超過k / 2)個數(shù)都是所有數(shù)的前k / 2小的數(shù)中的元素绿鸣,可排除
        if (nums1[i - 1] > nums2[j - 1])
            return findKth(nums1, vector<int>(nums2.begin() + j, nums2.end()), k - j);       //nums2的前j個數(shù)一定在k之前,所以在剩下的數(shù)中找第k - j大的數(shù)
        else
            return findKth(vector<int>(nums1.begin() + i, nums1.end()), nums2, k - i);
        
        //return 0;
    }
};

方法三:設(shè)l = nums.size()可發(fā)現(xiàn)如下規(guī)律:

  • 若l % 2 == 1暂氯,數(shù)組中位數(shù) = nums[l / 2] = nums[(l - 1) / 2] = (nums[l / 2] + nums[(l - 1) / 2])/ 2
  • 若l % 2 == 0潮模,數(shù)組中位數(shù) = (nums[l / 2] + nums[(l - 1) / 2])/ 2
class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size(), len2 = nums2.size();
        //保證nums1最短
        if (len1 > len2)
            return findMedianSortedArrays(nums2, nums1);
        if (len1 == 0)
            return (nums2[(len2 - 1) / 2] + nums2[len2 / 2]) / 2.0;
        
        int l = 0, r = len1 * 2;     //nums1較短,故中位數(shù)一定在len1及其后
        int l1, l2, r1, r2;
        while(l <= r)
        {
            int mid1 = (l + r) / 2;           //第一次分mid1 = len1
            int mid2 = len1 + len2 - mid1;         /第一次分mid2 = len2
            //mid1 = 0 —— 數(shù)組1整體都比中值大痴施,l1 > r2擎厢,中值在2中 
            l1 = (mid1 == 0)? INT_MIN : nums1[(mid1 - 1) / 2];                //第一次割一定在nums1的中位數(shù)上
            r1 = (mid1 == 2 * len1)? INT_MAX : nums1[mid1 / 2];

            //mid2 = 0 —— 數(shù)組2整體都比中值大,l2 > r1辣吃,中值在1中 
            l2 = (mid2 == 0)? INT_MIN : nums2[(mid2 - 1) / 2];                 //第一次割一定在nums2的中位數(shù)上
            r2 = (mid2 == 2 * len2)? INT_MAX : nums2[mid2 / 2];
            
            if(l1 > r2)        //說明中位數(shù)在數(shù)組一的更前半部或數(shù)組二的更后半部动遭,故減小mid1,增大mid2神得。說明數(shù)組一的后半部不用找了
                r = mid1 - 1;
            else if(l2 > r1)          //說明中位數(shù)在數(shù)組二的更前半部或數(shù)組一的更后半部厘惦,故減小mid2,增大mid1循头。說明數(shù)組一的前半部不用找了
                l = mid1 + 1;
            else               //l1 < r2 && l2 < r1绵估,又因為找的是中位數(shù),故兩個割分別在兩序列中間卡骂。說明Max(l1, l2)就是中位數(shù)国裳。
                break;
        }
        //當(dāng)兩數(shù)組數(shù)字總個數(shù)為奇數(shù)時,割將個數(shù)為奇數(shù)的那個數(shù)組的中位數(shù)分為兩個全跨,故max(l1, l2) =  min(r1, r2)
        return (max(l1, l2)+ min(r1, r2))/2.0;
    }
};
參考:

方法三圖示步驟分解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缝左,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子浓若,更是在濱河造成了極大的恐慌渺杉,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挪钓,死亡現(xiàn)場離奇詭異是越,居然都是意外死亡,警方通過查閱死者的電腦和手機碌上,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門倚评,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人馏予,你說我怎么就攤上這事天梧。” “怎么了霞丧?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵呢岗,是天一觀的道長。 經(jīng)常有香客問我蛹尝,道長后豫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任箩言,我火速辦了婚禮硬贯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘陨收。我一直安慰自己饭豹,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布务漩。 她就那樣靜靜地躺著拄衰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饵骨。 梳的紋絲不亂的頭發(fā)上翘悉,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機與錄音居触,去河邊找鬼妖混。 笑死老赤,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的制市。 我是一名探鬼主播抬旺,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼祥楣!你這毒婦竟也來了开财?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤误褪,失蹤者是張志新(化名)和其女友劉穎责鳍,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兽间,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡历葛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘀略。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啃洋。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖屎鳍,靈堂內(nèi)的尸體忽然破棺而出宏娄,到底是詐尸還是另有隱情,我是刑警寧澤逮壁,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布孵坚,位于F島的核電站,受9級特大地震影響窥淆,放射性物質(zhì)發(fā)生泄漏卖宠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一忧饭、第九天 我趴在偏房一處隱蔽的房頂上張望扛伍。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逆航。三九已至,卻和暖如春渔肩,著一層夾襖步出監(jiān)牢的瞬間因俐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抹剩,地道東北人撑帖。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像澳眷,于是被迫代替她去往敵國和親磷仰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容