LeetCode(4) ---- Median of Two Sorted Arrays

1.Problem

There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:
nums1 = [1, 3]
nums2 = [2]

The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

2.Translation

給兩個(gè)各自排好序的數(shù)組育特,然后找出他們兩個(gè)中的中間值壁却,如示例所示。然后給了時(shí)間復(fù)雜度的限制杆故。

3.My View

出去開一個(gè)大會(huì)跑回來還有各種各樣的事要做……但是還是先刷一道算法吧。

回來室友說這個(gè)很簡(jiǎn)單咨堤,然后做了n久埂伦,雖然有了想法,想法是合并->排序泛领,說起來應(yīng)該達(dá)不到n方的復(fù)雜度荒吏,但是無從下手。

然后室友說用了Python的庫(kù)函數(shù)渊鞋,排序(數(shù)組1+數(shù)組2)绰更。
雖然覺得直接調(diào)庫(kù)就沒啥意思了,但是還是寫了一個(gè)調(diào)庫(kù)的锡宋,更高端的有空再研究儡湾。

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        //構(gòu)建新數(shù)組
         int[] nums = new int[nums1.length+nums2.length];
        //將數(shù)組合并(采用arraycopy函數(shù))
        if(nums1.length>0&&nums2.length>0){
         System.arraycopy(nums1, 0, nums, 0, nums1.length);
         System.arraycopy(nums2, 0, nums, nums1.length, nums2.length);
        }else if(nums1.length>0&&nums2.length==0){
           System.arraycopy(nums1, 0, nums, 0, nums1.length); 
        }else if(nums2.length>0&&nums1.length==0){
            System.arraycopy(nums2, 0, nums, 0, nums2.length); 
        }
        //將數(shù)組排序(sort函數(shù))
        Arrays.sort(nums);
        //返回結(jié)果
        return (nums[(nums.length-1)/2]+nums[nums.length/2])/2.0;
    }
}

這里主要用了arraycopy和sort函數(shù),用來完成數(shù)組合并和排序执俩。

當(dāng)然徐钠,嗯,路過打個(gè)醬油啦役首!

于是抽空又寫了一個(gè)能說的過去的尝丐。
不過當(dāng)然不能跟大神比啦显拜。

6KBM92FU9_L_W%1GUTI2JW.png

連大眾算法都沒上。

public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
                 //構(gòu)建新數(shù)組
             int[] nums = new int[nums1.length+nums2.length];
             int num1_len = nums1.length,num2_len = nums2.length;
             int i = 0,j = 0,k = 0;
                //調(diào)整數(shù)組訪問順序  
             if(num1_len > num2_len){
                 return findMedianSortedArrays(nums2,nums1);
             }      
            while(i<num1_len||j<num2_len){
                 //余數(shù)據(jù)處理  
             if(i<=nums1.length-1&&j>nums2.length-1){
                 nums[k] = nums1[i];
                 i++;
                 k++;
                 continue;
             } 
             if(i>nums1.length-1&&j<=nums2.length-1){
                 nums[k] = nums2[j];
                 j++;
                 k++;
                 continue;
             }  
                 //正常數(shù)據(jù)處理
             if(nums1[i]<=nums2[j]){
                 nums[k] = nums1[i];
                 i++;
             }else{
                 nums[k] = nums2[j];
                 j++;
             }   
             k++;
            }    
                 //結(jié)果
            return (nums[(nums.length-1)/2]+nums[nums.length/2])/2.0;
        }

期間也是遇到大大小小的錯(cuò)誤爹袁,連續(xù)提交了幾次才成功远荠。算法的理念就是排序合并,這個(gè)想法是源自于數(shù)據(jù)結(jié)構(gòu)鏈表合并排序的題目失息,以前沒仔細(xì)寫過譬淳,今天算是拿數(shù)組練練手了。

真正官方的根时,
NB的在下面瘦赫。

Solution

Put left_A and left_B into one set, and put right_A and right_B into another set.

把A數(shù)組分成左右兩部分,B數(shù)組也分成左右兩部分蛤迎。

        left_part          |        right_part
    A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]
    B[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

然后如果我們確保

//左右長(zhǎng)度一致
len(left_part)=len(right_part)
//左部分最大值小于右部分最小值
max(left_part)≤min(right_part)

那么我們就會(huì)很輕易地得到答案
a = (max(left_part)+ min(right_part))/2

那么接下來我們要解決的問題就是如何滿足這兩個(gè)條件

//首先我們要求(i是A數(shù)組左部分确虱,j是B數(shù)組左部分,m是A的長(zhǎng)度替裆,
//n是B的長(zhǎng)度校辩,那么這樣很顯然就是讓A_left + B_left = A_right+B_right)
i+j=m?i+n?j 
//為了確保大小,我們結(jié)合剛開始給的表格來看
B[j?1]≤A[i] and A[i?1]≤B[j]

and then辆童?

Searching i in [0,m], to find an object i such that:
//在【0宜咒,m】區(qū)間搜索一個(gè)滿足條件的i
B[j?1]≤A[i]  and A[i?1]≤B[j],  where j = (m+n+1)/2 - i

這里一定要確保j是非負(fù)數(shù),那么要求就是m要比n小把鉴,否則可能會(huì)因?yàn)閙/2太大導(dǎo)致j是負(fù)數(shù)故黑。

同時(shí)我們?cè)诜治鲞@種情況的時(shí)候,不能忽視了一些極端數(shù)據(jù)庭砍,比如說空數(shù)組场晶,重復(fù)數(shù)據(jù)等
官方給出的解釋是,當(dāng)我們比較這些情況的時(shí)候

B[j?1]≤A[i]  and A[i?1]≤B[j],  where j = (m+n+1)/2 - i

如果他們不存在(數(shù)據(jù))怠缸,可以直接空過去

那么在搜索的過程中就出現(xiàn)了三種情況

(j=0  or  i = m  or B[j?1]≤A[i]) and
i = 0 or j=n or A[i?1]≤B[j]) 
Means ii is perfect, we can stop searching.
(j > 0 and i <m and B[j?1]>A[i]) 
Means ii is too small, we must increase it.
(i>0 and j<n and A[i?1]>B[j]) 
Means ii is too big, we must decrease it.

最后是Code

 public double findMedianSortedArrays(int[] A, int[] B) {
        //獲取長(zhǎng)度
        int m = A.length;
        int n = B.length;
        //確保長(zhǎng)度m<n(當(dāng)然在這里我們也可以用遞歸來實(shí)現(xiàn)诗轻,不過效率會(huì)低一點(diǎn))
        if (m > n) { 
            int[] temp = A; A = B; B = temp;
            int tmp = m; m = n; n = tmp;
        }
        //初始化變量
        int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
        //循環(huán)檢查A數(shù)組
        while (iMin <= iMax) {
            //i是A數(shù)組中心
            int i = (iMin + iMax) / 2;
            //J也就是我們公式里的j
            int j = halfLen - i;
            //接下來就是我們的三種情況
            //通過調(diào)整imin和imax兩個(gè)值來確定i,j的位置揭北,
            //也就是確保分片的合理性
            if (i < iMax && B[j-1] > A[i]){
                iMin = iMin + 1; // i is too small
            }
            else if (i > iMin && A[i-1] > B[j]) {
                iMax = iMax - 1; // i is too big
            }
             //當(dāng)i是一個(gè)合適的切片點(diǎn)的時(shí)候扳炬,開始查找右片最小值和左片最大值
            else { // i is perfect
                int maxLeft = 0;
                if (i == 0) { maxLeft = B[j-1]; }
                else if (j == 0) { maxLeft = A[i-1]; }
                else { maxLeft = Math.max(A[i-1], B[j-1]); }
                //奇數(shù)個(gè)直接返回中心點(diǎn)
                if ( (m + n) % 2 == 1 ) { return maxLeft; }

                int minRight = 0;
                if (i == m) { minRight = B[j]; }
                else if (j == n) { minRight = A[i]; }
                else { minRight = Math.min(B[j], A[i]); }
               //返回中值
                return (maxLeft + minRight) / 2.0;
            }
        }
        return 0.0;
    }

這個(gè)算法核心的地方還是在于分片。
同時(shí)這個(gè)算法也源自于高中的中值概念搔体,通過排除最小最大值來得到中值恨樟。

更多優(yōu)秀算法建議去LeetCode查看。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疚俱,一起剝皮案震驚了整個(gè)濱河市厌杜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌计螺,老刑警劉巖夯尽,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異登馒,居然都是意外死亡匙握,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門陈轿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來圈纺,“玉大人,你說我怎么就攤上這事麦射《耆ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵潜秋,是天一觀的道長(zhǎng)蛔琅。 經(jīng)常有香客問我,道長(zhǎng)峻呛,這世上最難降的妖魔是什么罗售? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮钩述,結(jié)果婚禮上寨躁,老公的妹妹穿的比我還像新娘。我一直安慰自己牙勘,他們只是感情好职恳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著方面,像睡著了一般放钦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上葡幸,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天最筒,我揣著相機(jī)與錄音,去河邊找鬼蔚叨。 笑死床蜘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔑水。 我是一名探鬼主播邢锯,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼搀别!你這毒婦竟也來了丹擎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蒂培,沒想到半個(gè)月后再愈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡护戳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年翎冲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媳荒。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抗悍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钳枕,到底是詐尸還是另有隱情缴渊,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布鱼炒,位于F島的核電站衔沼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏田柔。R本人自食惡果不足惜俐巴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望硬爆。 院中可真熱鬧欣舵,春花似錦、人聲如沸缀磕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)袜蚕。三九已至糟把,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間牲剃,已是汗流浹背遣疯。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凿傅,地道東北人缠犀。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像聪舒,于是被迫代替她去往敵國(guó)和親辨液。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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