題目描述
已知有兩個等長的非降序序列S1, S2, 設計函數求S1與S2並集的中位數。有序序列A0,A1,⋯,AN−1的中位數指A(N−1)/2的值,即第⌊(N+1)/2⌋個數(A0為第1個數)。
輸入格式:
輸入分三行。第一行給出序列的公共長度N(0<N≤100000),隨后每行輸入一個序列的信息,即N個非降序排列的整數。數字用空格間隔。
輸出格式:
在一行中輸出兩個輸入序列的並集序列的中位數。
輸入樣例1:
5 1 3 5 7 9 2 3 4 5 6
輸出樣例1:
4
題解
因為要求log n的解法,而且題目是非降序的序列,就自然而然想到最近上課教的二分搜索了。
這里有三種情況
1.a[mid]>b[mid] 那么我們取a的左邊(包括a)和b的右邊(包括b)比較
2.a[mid]<b[mid] 那么我們取a(包括a)的右邊和b的左邊(包括b)比較
3.a[mid]=b[mid] 此時a[mid]、b[mid]即為所求
但是有一個特殊情況就是當數組長度為偶數的時候
我舉個栗子
比如 這個樣例
a : 1 2 3 4 5 6
b : 7 8 9 10 11 12
round 1:a[mid]=3, b[mid]=9;
9>3,此時a的右邊包括a 是四個數,而b的左邊包括b是三個數,兩個序列長度不相等。
所以我們在遇到偶數長度的數組時,要在round 1的時候,應該取不等長的,a取第三個數,b取第四個數。
我們第一次取得兩個數組的長度是不等長的,但是我們這樣處理了以后,(后面的操作和對奇數長度數組一樣),
我們以后每次操作的長度就會相等了。(兩個數組肯定一個取左邊,一個取右邊)
#include<bits/stdc++.h> using namespace std; typedef long long ll; int a[100009]; int b[100009];
int binarysearch1(int l1, int r1, int l2, int r2) { int mid1=(l1+r1)/2; int mid2=(l2+r2+1)/2;//+1處理,可以在遇到偶數序列時處理 if (l1== r1&&l2 != r2) { if (a[l1] > b[r2])return b[r2]; else return a[l1]; } if (l2 == r2&&l1 != r1) { if (b[l2] > a[r1])return a[r1]; else return b[l2]; } if(l1==r1&&l2==r2) { if(a[l1]>b[l2]) return b[l2]; else return a[l1]; } else { if (l1 == r1 - 1 && l2 == r2 - 1) //當a、b數組都只剩兩個數字時 { mid1 = (l1 + r1) / 2; mid2 = (l2 + r2) / 2; } if (a[mid1]==b[mid2]) return a[mid1]; else if (a[mid1] > b[mid2]) binarysearch1(l1, mid1 ,mid2, r2); else binarysearch1(mid1, r1, l2, mid2); } } int main() { int n; cin >> n; for(int i=0; i<n; i++) cin >> a[i]; for(int i=0; i<n; i++) cin >> b[i]; cout << binarysearch1(0,n-1,0,n-1) << endl; }
算法時間及空間復雜度分析:因為每次都是二分,主函數中定義了n,進行了一次輸入,以及對數組的賦值,則t1(n) = O(n)+O(1),在 binarysearch1函數中,每次都進行三次判斷,t2(n)=O(1)+O(1)+O(1),由於進行二分操作,故該函數總共調用log n次. 總共的時間復雜度是O(n)=t1(n)+log n*t2(n),因此總時間復雜度為log n;
而空間復雜為O(1),因為沒有再開拓新空間。
心得:當判斷的條件很多時,也要耐心,仔細,寫好每一個if else語句,模擬出所有情況來。
