從0打卡leetcode之day 5 ---兩個排序陣列的中位數

帥地發表於2018-08-18

前言

我靠,才堅持了四天,就差點不想堅持了。不行啊,我得把leetcode上的題給刷完,不然怕是不好進入bat的大門。

題目描述

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2 。
請找出這兩個有序陣列的中位數。要求演算法的時間複雜度為 O(log (m+n)) 。你可以假設 nums1 和 nums2 均不為空。

示例
nums1 = [1, 3]
nums2 = [2]

中位數是 2.0
nums1 = [1, 2]
nums2 = [3, 4]

中位數是 (2 + 3)/2 = 2.5``

解題

最簡單粗暴的就是把這兩個陣列頭尾連線起來,然後重新給他們排序一下,氣泡排序相信你信手拈來,當然,你也可以裝逼用快速排序。

但是,如果這樣子做的話,題目給你的有序陣列就沒啥用了,和無序一個樣,所以這樣做是不行的。題目要求是時間複雜度不能超過O(log(n+m)),說實話,這個複雜度我是不知道怎麼做好,我的做法時間複雜度是O(n+m)。

具體是這樣的

居然兩個陣列都是有序的了,我們可以再弄一箇中間陣列,然後把兩個陣列各自從陣列頭開始比較,哪個元素小,我們就把它存在中間陣列。然後接下下一個元素一直比較下去。

我還是直接上程式碼吧。如下:

    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
            int m = nums1.length;
            int n = nums2.length;
            int t = m + n;//總長度
            int temp[] = new int[t];
            int i  = 0, j = 0, k = 0;
            double obj;//用來存目標值

            while(i < m && j < n){
                //把陣列中比較小的值轉移到temp陣列中
                if(nums1[i] < nums2[j]){
                    temp[k++] = nums1[i++];
                }else{
                    temp[k++] = nums2[j++];
                }
            }
            //把剩餘的轉移過去
        while (i < m){
                temp[k++] = nums1[i++];
        }
        while(j < n){
                temp[k++] = nums2[j++];
        }
        //兩個陣列的總個數是奇數還是偶數
        if(t % 2 == 0){//偶數
                obj = (temp[t/2] + temp[(t-1)/2]) / 2.0;
        }else{
                obj = temp[t/2];
        }

        return obj;
    }

雖然時間複雜度是O(n+m),但是提交的時候居然通過了,而且還打敗了93%的人。

不過,這裡還可以在優化,把時間複雜度降低到O((n+m)/2)。
就是說其實我們不用給整個temp陣列排序,我們只要求出前面一半的陣列元素就可以知道中間那個元素了,。例如不管一共是偶數個元素還是奇數個元素,我們讓temp存到下標為t/2就可以了。然後再來判斷t是奇數還是偶數…..

例如上面兩個示例,示例1一共有三個元素,那麼temp[t/2]=temp[1]=2。然後直接把temp[t/2]=temp[1]取出來返回就可以了。

示例2一共有4個元素,那麼temp[t/2]=temp[2]=3。由於是偶數,我們直接把temp[t/2]=3和temp[t/2-1]=2這兩個元素取出來處理之後返回就可以了。

至於程式碼這麼寫,我就不寫了。知道有這麼一回事就可以了。

如果你堅持想要O(log(n+m))的時間複雜度,那麼可以看官方給的答案:

連結:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/

相關文章