二分基礎入門

2021-08-08 18:13:01 字數 4248 閱讀 5390

二分查詢

又稱折半查詢,

對排好序的陣列,每次取這個數和陣列中間的數進行比較,複雜度是

o(logn)如:

設陣列為

a[n],查詢的數x,

如果x==a[n/2]

,則返回

n/2; 如果

x < a[n/2],則在

a[0]

到a[n/2-1]

中進行查詢;

如果x > a[n/2]

,則在a[n/2+1]

到a[n-1]

中進行查詢; 優點

是比較次數少,查詢速度快,平均效能好;其

缺點是要求待查表為有序表,且插入刪除困難。

條件:查詢的陣列必須要為有序陣列。

[cpp]

view plain

copy

/*歸的二分查詢

arrat:陣列 , low:上界;  high:下界;  target:查詢的資料; 返回target所在陣列的下標 

*/int

binarysearch(

intarray, 

intlow, 

inthigh, 

inttarget)   

if(target == array[middle])   

if(target < array[middle])   

if(target > array[middle])    

}  

[cpp]

view plain

copy

/*非遞迴的二分查詢 

arrat:陣列 , n:陣列的大小;  target:查詢的資料; 返回target所在陣列的下標 

*/int

binarysearch2(

intarray, 

intn, 

inttarget)  else

if(target < array[middle])  else

if(target > array[middle])   

}  return

-1;  

}  

推薦使用非遞迴的方式,因為遞迴每次呼叫遞迴時有用堆疊儲存函式資料和結果。

能用迴圈的盡量不用遞迴。

c++如何跳出多層迴圈

》中提到的抽籤問題進行分析。 4

),資料大時其計算量會大的驚人。為便於分析,將之前**帖至如下:

[cpp]

view plain

copy

**  

抽籤問題  

解決方案,複雜度n^4   

*/   

void

drawlots()   

bool

result = 

false

;  bool

isbreakloop = 

true

;  int

_sum = 0;  

for(

inta = 0; a < numofcard && isbreakloop; a ++)     

}  }  

}  }  

cout << "_sum:"

<< _sum << 

"  "

<< 

"sum:"

<< sum << endl;  

if(result) else

cout<<"no"

<

}  

最內層迴圈所做事如下: k

a + k

b+ k

c+ k

d= m

移項後如下: k

d= m - (k

a + k

b+ kc)

到第四層迴圈時,其實k

a ,kb,k

c已經知道,那問題也就變成了對k

d的查詢,我們可用上面講的二分查詢,複雜度就降為o(n

3logn).實現如下:

[cpp]

view plain

copy

/**抽籤問題 

解決方案,複雜度n^3 * log(n)

*/void

drawlots2()   

//對陣列進行排序 

sort(k, k + numofcard);  

intindex = -1;  

bool

isbreakloop = 

true

;  for

(int

a = 0; a < numofcard && isbreakloop; a ++)   

}  }  

}  if

(index >= 0) else

cout<<"no"

<

}  

根據上一步的優化方式,我們可以進一步對內側兩層迴圈(

也就是第三層和第四層

)進行思考: k

c+ k

d= m - (ka 

+ kb)

我們不能直接對kc

+ kd

進行查詢,但是可以預先列舉出ka 

+ kb的n2

種數值並排序,再對kc

+ kd

進行十分查詢。列出列舉o(n

2),排序

o(n2

logn), 迴圈

o(n2

logn),所以總的複雜度降為

o(n2logn)

,實現如下:

[cpp]

view plain

copy

/**抽籤問題 

解決方案,複雜度n^2 * log(n)

*/void

drawlots3()   

intcdnum = numofcard*(numofcard+1)/2;  

intcdsum[cdnum];  

inti = 0;  

for(

inta=0; a

for(

intb=i; b

cdsum[i ++] = k[a] + k[b];  

}  }  

//對陣列進行排序 

sort(cdsum, cdsum + cdnum);  

intindex = -1;  

bool

isbreakloop = 

true

;  for

(int

a = 0; a < numofcard && isbreakloop; a ++)   

}  }  

}  if

(index >= 0) else

cout<<"no"

<

}  

上面列舉ka 

+ kb

時其實是有重複的,因為k[i] + k[j] == k[j] + k[i]

,去除重複值之後,ka 

+ kb

值的個數是n(n+1)/2

。至於n(n+1)/2

怎麼來,可以簡單推導如下:

n     m

1     1

2      2+1

3     3+2+1

4     4+ 3+2+1

......

實現如下:

[cpp]

view plain

copy

/**抽籤問題 

解決方案,複雜度n^2 * log(n)

*/void

drawlots3_1()   

intcdnum = numofcard*numofcard;  

intcdsum[cdnum];  

for(

inta=0; a

for(

intb=0; b

cdsum[a*numofcard + b] = k[a] + k[b];  

}  }  

//對陣列進行排序 

sort(cdsum, cdsum + cdnum);  

intindex = -1;  

bool

isbreakloop = 

true

;  for

(int

a = 0; a < numofcard && isbreakloop; a ++)   

}  }  

}  if

(index >= 0) else

cout<<"no"

<

}  

python二分查詢基礎 005 入門

1.問題描述 給定乙個排序的整數組 公升序 和乙個要查詢的目標整數target,查詢到target第1次出現的下標 從0開始 如果target不存在於陣列中,返回 1 2.問題示例 輸入陣列 1,4,5,5,7,7,8,9,10 和目標整數1.輸出其所在的位置為0,即第1次出現在第0個位置。輸入陣列...

二分入門題

在乙個遞增的序列裡,查詢元素是否存在,若存在輸出yes,不存在輸出no.本題多組資料,首先輸入乙個數字n,然後輸入n個數,資料保證數列遞增,然後再輸入乙個查詢數字。若存在輸出yes,不存在輸出no.4 1 3 5 8 3 yes include include includeusing namesp...

二分簡單入門

參考文章 二分.1.最大化最小值 相當於n個東西分給m個人,使得每個人 至少拿x個 那麼每個人拿夠了 就走,給後面的人多留一點,只要能分夠 m個人 就是true,多的全 扔給最後乙個人就是了.2.最小化最大值 相當於n個東西分給m個人,每個人 至多能拿x個 那麼每個人盡可能 多拿一點,給後面的人少留...