題目:
給定乙個源區間[x,y](y>=x)和n個無序的目標區間[x1,y1] [x2,y2] [x3,y3]…[xn,yn],判斷源區間[x,y]是不是在目標區間內?
例如,給定源區間[1,6]和一組無序的目標區間[2,3] [1,1] [3,9],即可認為區間[1,6]在區間[2,3] [1,1] [3,9]內,因為目標區間實際上是[1,9]。
基本思想:
解法一
問題的本質在於對目標區間的處理。乙個比較直接的思路即將源區間[x,y](y>=x)和n個無序的目標區間[x1,y1] [x2,y2] [x3,y3]…[xn,yn]逐個投影到座標軸上,只考察源區間未被覆蓋的部分。如果所有的目標區間全部投影完畢,仍然有源區間沒有被覆蓋,那麼源區間就不在目標區間之內。
仍以[1,6]和 [2,3] [1,2] [3,9]為例,考察[1,6]是否在[2,3] [1,2] [3,9]內:
源區間為[1,6],那麼最初未被覆蓋的部分為,將按順序考察目標區間[2,3] [1,2] [3,9] 。
將目標區間[2,3]投影到座標軸,那麼未被覆蓋的部分都變為。
將目標區間[1,2]投影到座標軸,那麼未被覆蓋的部分將變為。
將目標區間[3,9]投影到座標軸,那麼未被覆蓋的部分將變為,即可說明[1,6]是在[2,3] [1,2] [3,9]內。
由以上步驟可以看出,每次操作,尚未被覆蓋的區間陣列大小最多增加1(當然可能減少),而每投影乙個新的目標區間,計算有哪些源區間陣列被覆蓋需要o(logn)的時間複雜度,但是更新尚未被覆蓋的區間陣列需要o(n)的時間複雜度,所以總的時間複雜度為o(n^2)。
這個解法的複雜度高,而且如果要對k組源區間進行查詢,那麼時間複雜度會增大單次查詢的k倍。有沒有更好的解法,使得單次查詢的時間複雜度降低,並且使k次查詢的時間複雜度小於單次查詢的時間複雜度的1/k倍呢?
解法二
一種值得嘗試並已經在本書中多次運用的思路是,對現有的陣列進行一些預處理(如合併、排序等),將無序的目標區間合併成幾個有序的區間,這樣就可以進行區間的比較。
因此,問題就變成了如何將這些無序的陣列轉化為乙個目標區間。
首先可以做一次資料初始化的工作。由於目標區間陣列是無序的,因此可以對其進行合併操作,使其變得有序。即先將目標區間陣列按x軸座標從小到大排序(排序時可採用快速排序等),如[2,3] [1,2] [3,9]-> [1,2] [2,3] [3,9];接著掃瞄排序後的目標區間陣列,將這些區間合併成若干個互不相交的區間,如[1,2] [2,3] [3,9]-> [1,9]。
然後在資料初始化的基礎上,運用二分查詢(為什麼?)來判定源區間[x,y]是否被合併後的這些互補相交的區間中的某乙個包含。如[1,6]被[1,9]包含,則可說明[1,6]在[2,3] [1,2] [3,9]內。
這種思路相對簡單,時間複雜度計算如下:
排序的時間複雜度:o(n*logn)(n為目標區間的個數);
合併的時間複雜度:o(n);
單次查詢的時間複雜度:logn;
所以總的時間複雜度為o(n*logn)+ o(n)+ o(k*logn)= o(n*logn) + o(k*logn),k為查詢的次數,合併目標區間陣列的初始化資料操作只需要進行一次。
這樣不僅單次查詢的時間複雜度降低了,而且對於k>>n的情況,處理起來也會方便很多。
總結
解法一採用利用目標區間來分割源區間的方法,會增加儲存空間;解法二採用合併的方法,既簡單又節省了空間。
解法二源**:
#include using namespace std;
void swap(int a,int b)
void quicksort(int low,int high,int *a,int *b)
d[temp]=b[length-1];
number=temp+1;
cout
return true;
else
return false;
} while(begin<=end)
bool projection(int *a,int *b,int n,int x,int y)
{ quicksort(0,n-1,a,b);
coutflag;//0第乙份資料,1第二份資料
if(!flag)
{ int n=4;
int *a=new int [n];//對應 x1, x2, ... , xn
int *b=new int [n];//對應 y1, y2, ... ,yn
a[0]=1;
a[1]=5;
a[2]=2;
a[3]=10;
b[0]=3;
b[1]=9;
b[2]=4;
b[3]=11;
int x=6;
int y=10;
if(projection(a,b,n,x,y))//1結果在目標區間內,0不在
引用:
程式設計之美 2 19 區間重合判斷
題目大意 給定源區間 x,y x y 和 n個無序的目標區間 xi,yi 1 i n 判斷源區間是否在目標區間內。分析 書中介紹了兩種解法。第一種 將目標區間投影到源區間,看最終未被覆蓋的區間是否變為。這種方法的複雜度無疑是很高的。o n 2 另外,對於k組源區間查詢,其複雜度是單次的k倍。第二種 ...
程式設計之美 2 19 區間重合判斷
給定乙個源區間 x,y y x 和n個無序的目標區間 x1,y1 x2,y2 xn,yn 判斷源區間 x,y 是不是在目標區間內 eg,給定乙個源區間 1,6 和一組無序的目標區間 2,3 1,2 3,9 即可認為 1,6 在區間 2,3 1,2 3,9 內 因為目標區間合併之後,實質為 1,9 i...
程式設計之美2 19區間重合判斷
區間重合判斷 比如,給出待判斷區間 x,y 如 1,6 以及目標區間 x1,y1 x2,y2 xi,yi 如 2,3 1,2 3,9 判斷 1,6 是否在目標區間中 做法 先把根據各個目標區間的第乙個元素xi排序 可用快排 然後將目標區間中可以合併的區間進行合併,然後 在目標區間的xi中用二分查詢來...