LeetCode4. Median of Two Sorted Arrays---vector實現O(log(m+n)--- findkth

這道題目和PAT上的1029是同一題。可是PAT1029用O(m+n)的時間複雜度(題解)就能夠,這道題要求是O(log(m+n))。html

這道題花費了我一個工做日的時間來思考。由於是log於是一直思考如何進行二分,想着是兩個vector分別二分,但一直想不到合適的解法,就是無窮盡的if else數組

後來看了題解。思路是從兩個有序數組中尋找第k小的數。spa

<1>花了很長時間在調試上,結果發現是少了一個return,期間還不停懷疑本身寫遞歸的能力。。。要被本身戰勝了,調代碼真是一件細小卻很耗費心神的事情。指針

<2>對vector的使用也是醉了。調試

思路以下:code

  咱們先假設nums1nums2數組中元素個數都是大於 k/2 的,且從 0 開始編號,那麼咱們比較 a = nums1[k/2 - 1] 和 b = nums2[k/2 - 1]。htm

  (1)若是 a < b 那麼 nums1[0] 到 nums1[k/2 - 1] 這 k/2 個數在合併後的有序數組中,必定在第 k 小的數左邊。爲何呢?blog

  咱們發現,nums1數組中比 a 小的數一共是 k/2 - 1 個。nums2數組中比 a 小的數最多有 k/2 - 1 個。於是合併之後比 a 小的數最多有k/2 - 1 + k/2 - 1 < k - 2。遞歸

  也就是說 a 最可能是第 k-1 小的數。因此說nums1數組前 k/2 個數能夠剔除了。get

  (2)若是 a > b 同理,剔除掉 nums2數組前 k/2 個數。

  (3)若是 a = b,a 即爲所求。

  每次剔除掉 k 一半個元素,於是時間複雜度是O(logk),對於此題,k = (m+n)/2 因此時間複雜度是O(log(m+n))

 

考慮實際狀況:

  若是nums1nums2數組中元素個數不足 k/2 個的話,通常狀況下,咱們只須要知足二者前面的總數目爲 k 便可,原理和上述的原理是相似的,再也不贅述。

  此外還須要考慮特殊狀況,

  (1)一個數組爲空,則放回另外一個數組的第 k 大;

  (2)k==1則直接返回min(nums1[0],nums2[0])。

在實際實現的時候,因爲輸入是vector,它是一個動態數組,能夠實時增長或刪除元素,可是沒法向普通數組/指針同樣任意指定起始位置和結束爲止,於是只好使用了刪除操做

erase(iter1,iter2),刪除[iter1,iter2)之間的元素。 

 1 class Solution {
 2 public:
 3     double findkth(vector<int>& nums1,vector<int>& nums2, int k)
 4     {
 5         int m = nums1.size(),n = nums2.size();
 6         if(m > n)
 7             return findkth(nums2,nums1,k);//error 1. forget the "return";
 8         if(m == 0)
 9             return double(nums2[k - 1]);//error 2. write as nums2[n - 1];
10         if(k == 1)
11         {
12             return double(min(nums1[0],nums2[0]));
13         }
14         int pa = min(k / 2,m), pb = k - pa;
15         if(nums1[pa - 1] < nums2[pb - 1])
16         {
17             nums1.erase(nums1.begin(),nums1.begin() + pa);
18             return findkth(nums1,nums2,k - pa);
19         }
20         else if(nums1[pa - 1] > nums2[pb - 1])
21         {
22             nums2.erase(nums2.begin(),nums2.begin() + pb);
23             return findkth(nums1,nums2,k - pb);
24         }
25         else
26             return double(nums1[pa - 1]);
27     }
28     double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
29         int len1 = nums1.size(),len2 =  nums2.size();
30         int len = len1 + len2;
31         vector<int> cop1(nums1),cop2(nums2);
32         if(len % 2)
33         {
34             return findkth(nums1,nums2,len / 2 + 1);
35         }
36         else
37         {
38             double t1=findkth(nums1,nums2,len / 2),t2=findkth(cop1,cop2,len / 2 + 1);
39             return (t1 + t2) / 2;
40         }
41     }
42 };

 

刪除vector的元素須要①額外備份一下數組,②刪除操做。無謂的耗時,於是從新實現成手動標記數組的起始位置。只須要在上面實現方法的基礎上 + star就能夠了,原理都是同樣的。

 1 class Solution {
 2 public:
 3     double findkth(vector<int>& nums1,int st1,int ed1,vector<int>& nums2, int st2,int ed2,int k)
 4     {
 5         int m = ed1 - st1,n = ed2 - st2;
 6         if(m > n)
 7             return findkth(nums2,st2,ed2,nums1,st1,ed1,k);//error 1. forget the "return";
 8         if(m == 0)
 9             return double(nums2[st2 + k - 1]);//error 2. write as nums2[n - 1];
10         if(k == 1)
11         {
12             return double(min(nums1[st1],nums2[st2]));
13         }
14         int pa = min(k / 2,m), pb = k - pa;
15         if(nums1[st1 + pa - 1] < nums2[st2 + pb - 1])
16         { 
17             return findkth(nums1,st1 + pa,ed1,nums2,st2,ed2,k - pa);
18         }
19         else if(nums1[st1 + pa - 1] > nums2[st2 + pb - 1])//error 3. forget the "st2 +";
20         {
21             return findkth(nums1,st1,ed1,nums2,st2 + pb,ed2,k - pb);
22         }
23         else
24             return double(nums1[st1 + pa - 1]);
25     }
26     double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
27         int len1 = nums1.size(),len2 =  nums2.size();
28         int len = len1 + len2;
29         if(len % 2)
30         {
31             return findkth(nums1,0,len1,nums2,0,len2,len / 2 + 1);
32         }
33         else
34         {
35             double t1 = findkth(nums1,0,len1,nums2,0,len2,len / 2),t2 = findkth(nums1,0,len1,nums2,0,len2,len / 2 + 1);
36             return (t1 + t2) / 2;
37         }
38     }
39 };
相關文章
相關標籤/搜索