03二分查詢

2021-10-16 19:35:13 字數 3449 閱讀 8427

"""

整數二分要注意邊界問題 不然特別容易出現死迴圈

二分的本質是邊界問題

1.mid=(l+r)//2

2.檢查mid處是否滿足性質

在二分左邊時不需要+1 二分右邊時需要+1

二分必須要保證有解(題目可能無解,我們可以通過最後的邊界來判斷題目是否有解)

"""def

main()

: n, m =

map(

int,

input()

.split())

q =list

(map

(int

,input()

.split())

)# q = [int(x) for x in input().split()]

while m >0:

x =int(

input()

) l, r =

0, n -

1while l < r:

# 找第乙個點 判斷mid的取值是否比要找的值大 如果大的話第乙個相等值應在mid的左邊 令r=mid 否則l=mid+1

mid =

(l + r)

>>

1if q[mid]

>= x:

r = mid

else

: l = mid +

1if q[l]

!= x:

print

('-1 -1'

)else

:print

(l, end=

' ')

l, r =

0, n -

1while l < r:

# 找第二個點 判斷mid的取值是否比要找的值小 如果小的話最後乙個相等值應在mid的右邊 令l=mid 否則r=mid-1

mid =

(l + r +1)

>>

1if q[mid]

<= x:

l = mid

else

: r = mid -

1print

(l, end=

'\n'

) m -=

1if __name__ ==

'__main__'

:"""

這裡要注意邊界的問題

注意在找第乙個點的,即第乙個相等數的時候,mid的取值為(l+r)>>1

取最後乙個相等數時,mid的取值為(l+r+1)>>1

這裡記住模板就好了 具體的越界情況 有點難想emmm 跟著大哥(y總)走

"""main(

)

在找相匹配的數x的起始位置和終止位置,可以把初始的序列看成兩部分,第一部分≤x,第二部分≥x,那麼,第二部分的第乙個,即為x的起始位置(第二部分都是≥x的,),第一部分的最後乙個(第一部分都是≤x的,再大就>x了),即為終止位置。

而為了防止整數數列**現越界問題,我們可以記住y總的模板,即求初始位置(第二部分的第乙個,實質則是求數列中≥x的那部分)時,mid=(l+r+1)>>1,求終止位置(第一部分的最後乙個,即數列中≤x的那部分),mid=(l+r)>>1,不需要+1。

除此以外,求起始位置和終止位置的演算法也可以封裝成函式,然後調整乙個用法即可,下面是封裝成函式的寫法(只有函式,和上面基本一樣,只是把兩份內容單獨拎出來而已):

def

find_first

(q, l, r, x)

:"""

尋找起始位置

:param q: 數列

:param l: 數列的最左邊下標,0

:param r: 數列的最右邊下標,n-1

:param x: 要查詢的數

:return: 返回數的起始位置或者-1

"""while l < r:

mid =

(l + r)

>>

1if q[mid]

>= x:

r = mid

else

: l = mid +

1if q[l]

!= x:

return-1

else

:# 輸出結束時l和r是相等的,所以輸出哪個無所謂

return l

deffind_last

(q, l, r, x)

:"""

尋找終止位置

:param q: 數列

:param l: 數列的最左邊下標,0

:param r: 數列的最右邊下標,n-1

:param x: 要查詢的數

:return: 返回數的終止位置或者-1

"""while l < r:

mid =

(l + r +1)

>>

1if q[mid]

<= x:

l = mid

else

: r = mid -

1if q[l]

!= x:

return-1

else

:# 輸出結束時l和r是相等的,所以輸出哪個無所謂

return l

上面是整數中的二分查詢,整數中的二分查詢要注意邊界問題,相應的解決辦法提現在mid的處理上。

而在浮點數的二分法中,因為沒有整除,所以不用考慮邊界問題,思想和整數的二分法相同(就是不用考慮邊界問題),當他的區間足夠小的時候,我們就可以認為他已經是乙個數了,可以返回的l或者r處的值(此時已經「相等」了)。區間足夠小的處理上,可以這樣:

1.加上區間控制語句

while r - l >1e-

6:# 10^-6

pass

# 具體操作

2.直接將方法執行100次,次數夠多,那邊界到時候一定足夠小

for x in

range

(100):

pass

# 具體操作

相應的實際問題,求乙個數的平方根:

def

main()

:"""輸入乙個數,求它的平方根"""

x =int(

input()

) l, r =

0, x

while r - l >1e-

6:# 10^-6

mid =

(l + r)/2

if mid * mid >= x:

r = mid

else

: l = mid

print

(l)if __name__ ==

'__main__'

: main(

)

LeetCode 03 二分查詢

注意 二分查詢中關於mid的選取 while left right 和 while left right 的區別 while left right 表示在區間中還剩下乙個元素的時候,停止迴圈 來自 leetcode liweiwei1419 對於二分搜尋編碼的建議在迴圈體內考慮如何縮減待搜尋區間,也...

迭代二分查詢二分查詢

在寫這篇文章之前,已經寫過了幾篇關於改迭代二分查詢主題的文章,想要了解的朋友可以去翻一下之前的文章 bentley在他的著作 writing correct programs 中寫道,90 的計算機專家不能在2小時內寫出完整確正的二分搜尋演算法。難怪有人說,二分查詢道理單簡,甚至小學生都能明確。不過...

1128 二分 二分查詢

時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 描述nettle最近在玩 艦 因此nettle收集了很多很多的船 這裡我們假設nettle氪了很多金,開了無數個船位 去除掉重複的船之後,還剩下n 1 n 1,000,000 種不同的船。每一艘船有乙個稀有值,任意兩艘船的稀有...