二分法總結 (以後直接就是抄板子了!)

2021-09-01 23:49:54 字數 3189 閱讀 2455

這兩天又碰到了用到了二分法的題,但是由於我之前學的不是很清楚,許多二分的題都是憑感覺寫出二分格式,然後wa之後憑感覺調整(竟然還能a過!!),因此再次碰到之後就感覺還是需要總結一下,要不然以後太浪費時間了。

我們用套路的方法來二分:

對於乙個區間[l,r],滿足 迴圈不變式: 

arr[l]<=key    arr[r]>=key

對於區間[l,r]裡面存在元素則表示還在區間內,根據不同的狀態,

判斷 arr[mid]==key 時的區間縮減狀態 

滿足迴圈不變式:arr[l]<=key&&arr[r]>=key 

key在區間[l,r]中,

arr[mid]==key時返回mid即可 

若最後區間[l,r]中沒有元素,則說明key不再陣列中,返回-1即可 

int search(int *arr,int n,int key)

return -1;//沒有找到

}

例題:hdu-3763-cd  題解:

hdu-2141-can you find it?   題解:

滿足迴圈不變式:arr[l]<=key&&arr[r]>=key 

key在區間[l,r]中, 

arr[mid]==key時:

因為要查詢第乙個與key相等的元素,因此此時mid可能不是第乙個與key相等的元素,因此區間縮小[l,mid-1]

當區間中沒有元素的時候,此時必定 r>1;

if(arr[mid]>key)//此時key必定在 [l,mid-1] 區間

r=mid-1;

else if(arr[mid]

滿足迴圈不變式:arr[l]<=key&&arr[r]>=key 

key在區間[l,r]中, 

arr[mid]==key時:

因為要查詢最後乙個與key相等的元素,因此此時mid可能不是最後乙個與key相等的元素,因此區間縮小[mid+1,r]

當區間中沒有元素的時候,此時必定 r=key ,r不變,l+1,答案為r。 

如果最後一次 l!=r ,則r=l+1,

若arr[mid]=key,mid==l所以結果是r 

若arr[mid]==key,轉成了l==r狀態 

int search_last_key(int *arr,int n,int key)

例題:hdu-6383-p1m2,題解:

poj-1064-cable master,題解:

hdu-hdu-1969-pie,        題解:

poj-3258-river hopscotch  題解:

hdu-2199-can you solve this equation?  題解:

滿足迴圈不變式:arr[l]<=key&&arr[r]>=key 

key在區間[l,r]中, 

arr[mid]==key時:

因為要查詢第乙個大於等於key的元素,因此此時mid可能不是第乙個與key相等的元素,因此區間縮小[l,mid-1],

如果此時arr[r]=key ,l不變,r-1,答案為l。 

如果最後一次 l!=r ,則r=l+1,

若arr[mid]=key,mid==l所以結果是

lint search_morefirst(int *arr,int n,int key)

{//找第乙個大於等於key的元素

int l=0,r=n-1,mid;

while(l<=r)

{ mid=(l+r)>>1;

if(arr[mid]>key)//顯而易見,key在[l,mid-1]區間

r=mid-1;

else if(arr[mid]

滿足迴圈不變式:arr[l]<=key&&arr[r]>=key 

key在區間[l,r]中, 

按照迴圈不變式很容易就能推出過程 

int search_more_frist(int *arr,int n,int key)

{//找第乙個大於key的元素的位置

int l=0,r=n-1,mid;

while(l<=r)

{ mid=(l+r)>>1;

if(arr[mid]>key)// key在[l,mid-1]區間

r=mid-1;

else if(arr[mid]例題:hdu-5101-select        題解:

滿足迴圈不變式:arr[l]<=key&&arr[r]>=key 

key在區間[l,r]中, 

arr[mid]==key時:

因為要查詢最後乙個小於等於key的元素,因此此時mid可能不是最後乙個與key相等的元素,因此區間縮小[mid+1,r],

如果此時arr[l]>key,那麼最後結束的時候必定l一直不變,r在l-1,即mid處 。 

當區間中沒有元素的時候,此時必定 r=key ,r不變,l-1,答案為r。 

如果最後一次 l!=r ,則r=l+1,

若arr[mid]=key,mid==l所以結果是r

若arr[mid]==key,轉成了l==r狀態

int search_morelast(int *arr,int n,int key)

{//找最後乙個小於等於key元素的位置

int l=0,r=n-1,mid;

while(l<=r)

{ mid=(l+r)>>1;

if(arr[mid]>key)// key在[l,mid-1]區間

r=mid-1;

else if(arr[mid]例題:hdu-5101-select        題解:

滿足迴圈不變式:arr[l]<=key&&arr[r]>=key 

key在區間[l,r]中, 

按照迴圈不變式很容易就能推出過程 

int search_morelast(int *arr,int n,int key)

{//找最後乙個小於key元素的位置

int l=0,r=n-1,mid;

while(l<=r)

{ mid=(l+r)>>1;

if(arr[mid]>key)// key在[l,mid-1]區間

r=mid-1;

else if(arr[mid]未完待續......

以後碰到其他的狀態的話會繼續補充的。

二分法 總結

1 二分查詢 binarysearch 二分查詢又稱折半查詢,它是一種效率較高的查詢方法。二分查詢要求 線性表是有序表,即表中結點按關鍵字有序,並且要用向量作為表的儲存結構。不妨設有序表是遞增有序的。2 二分查詢的基本思想 二分查詢的基本思想是 設r low,high 是當前的查詢區間 1 首先確定...

二分法細節總結

二分法的思想很容易理解,但是細節處理卻是乙個難點。很容易就容易出錯。這裡總結一下這些細節。區間為 left,right 情況 右邊指標取不到元素 初始化 left 0 right arr.length 迴圈條件 left right 注意事項 left 的更新是取到值的情況 right的更新是不取到...

二分法小總結

主要分為兩種 區間按序列劃分和區間按值劃分 區間按序列劃分 這種比較常見,一般是針對有序陣列或者部分有序陣列 如旋轉有序陣列 m是序列的中點,不斷的縮小區間。33 81 153 154 69 162 4 74 區間按值劃分 主要是無序陣列會使用,m取可能結果的最小值和最大值的中值,所以就是不停的猜m...