第二章上機實踐總結

1. 題目:

已知有兩個等長的非降序序列S1, S2, 設計函數求S1與S2並集的中位數。有序序列ios

A0, A1, … ,AN−1的中位數指A(N−1)/2的值,即第⌊(N+1)/2⌋個數(A​ 0爲第1個數)算法

 

輸入格式:數組

輸入分三行。第一行給出序列的公共長度N(0<N≤100000),隨後每行輸入一個序列的信息,即N個非降序排列的整數。數字用空格間隔。函數

 

輸出格式:spa

在一行中輸出兩個輸入序列的並集序列的中位數設計

 

2. 問題描述:

題目的本意就是求兩個長度相同的序列的有序交集的中位數,雖然兩個序列是有序序列,可是如何求兩個序列的合併中位數就很難,並且數據集裏也可能有重複的數字!排序

 

3. 思路:

例子先行:遞歸

 

輸入樣例:ci

5io

1 3 5 7 9

2 3 4 5 6

下標:      0     1     2     3     4

sequnce1:      1     3     5     7     9

sequence2:    2     3     4     5     6

咱們先看看兩個序列的中位數:5 和 4 ,比較一下,發現:序列1中位數 比 序列2的大,嗯哼? 並且這兩個序列有序

 

那不就代表 序列1 的 中位數以前的數都比 序列2 中位數在以後的都小嗎??(以下)

x x x 2 x x 3 x x x x x 7 x x 9,因此就確立了這樣的一個相對排序

那麼咱們對於 序列1 的 中位數以後的數都比 序列2 中位數在以前的再進行相同的操做,就能夠不斷地縮小範圍。

直到! 上下序列只剩下4個數的時候(即序列1剩2個數,序列2也剩2個數),咱們再進行歸併排序,這時候的中位數,就是咱們要的中位數了

 

解題過程就是:比較當前兩個數組的中位數,中位數大的數組,遞歸左子數組,中位數小的遞歸右子數組,

 

4. 代碼:

#include<iostream>

 

using namespace std;

 

 

int middlevalue(int*L, int*R,int L_lindex,int L_rindex,int R_lindex,int R_rindex)

{

       int L_mid = (L_lindex + L_rindex)/2;

       int R_mid = (R_lindex + R_rindex+1)/2;

       if(L_rindex-L_lindex == 1&& R_rindex - R_lindex==1)

       {

              int count = 0;

              int p1=L_lindex,p2= R_lindex;

              while(count!=2)

              {

                     if(L[p1]<R[p2])

                {

                      count++;

                      if(count==2) return L[p1];

                      p1++;

                }

                else if(L[p1]>=R[p2])

                {

                    count++;

                    if(count==2) return R[p2];

                    p2++;

                }

              }

      

       }

       if(R[R_mid]>L[L_mid])

       {

              middlevalue(L,R,L_mid,L_rindex,R_lindex,R_mid);

       }

       else if(R[R_mid]<=L[L_mid])

       {

              middlevalue(L,R,L_lindex,L_mid,R_mid, R_rindex);

       }

      

}

 

 

int main()

{

       int L[100005] = {0};

       int R[100005] ={0};

       int n;

       cin>>n;

       for(int i=0;i<n;i++)

       {

              cin>>L[i];

       }

       for(int i=0;i<n;i++)

       {

              cin>>R[i];

       }

       if(n==1)

       {

              cout<<(L[0]<R[0]?L[0]:R[0]);

       }

       else

       cout<<middlevalue(L, R, 0 , n-1 ,0,n-1);

}

5. 算法實踐複雜度分析:

1. 雖然是兩個數組,每次只用一次遞歸,因此時間複雜度爲 log2n

2 .每次計算兩次中位數: 2*log2n

3. 判斷是否遞歸 log2n

4. 最後歸併求中位數:while – 2, if – 2 , 內部處理:3*2 +2

5. 因此最後時間複雜度 O(log2n)

6. 總結:

自我疑惑:不知道如何證實:不斷縮小比較範圍後最後歸併的中位數就是整個序列的中位數,不具完備性。

對於int R_mid = (R_lindex + R_rindex + 1)/2; 而int L_mid = (L_lindex + L_rindex)/2;爲何R_mid的計算中要加入1呢,是爲了當分割數組是偶數時,兩個序列的分割大小能一致

其實呢,分治的形式有不少,此次收穫了使用二分比較,而不是插值,仍是蠻驚訝的

相關文章
相關標籤/搜索