程式設計之美2 19 區間重合判斷

2021-07-02 03:12:24 字數 2749 閱讀 3493

題目:

給定乙個源區間[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中用二分查詢來...