這兩天又碰到了用到了二分法的題,但是由於我之前學的不是很清楚,許多二分的題都是憑感覺寫出二分格式,然後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...