前言
我靠,才堅持了四天,就差點不想堅持了。不行啊,我得把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/
完