LeetCode 二分查詢

2021-10-23 05:47:25 字數 3972 閱讀 6026

二分查詢也稱為折半查詢,每次都能將查詢區間減半,這種折半特性的演算法時間複雜度為 o(logn)。

中值計算

有兩種計算中值 m 的方式:

l + h 可能出現加法溢位,也就是說加法的結果大於整型能夠表示的範圍。但是 l 和 h 都為正數,因此 h - l 不會出現加法溢位問題。所以,最好使用第二種計算法方法。

69. x 的平方根

實現int(math.sqrt(x))函式。

示例

輸入: 4

輸出: 2

輸入: 8

輸出: 2

說明: 8 的平方根是 2.82842..., 由於返回型別是整數,小數部分將被捨去。

解法

不斷縮小區間,在將該區間中位數與x做比較

以30為例,區間縮小為[0,16] -> [0,7] -> [4,7] -> [4,5] -> [5,5]

class

solution

:def

mysqrt

(self, x:

int)

->

int:

# 為了照顧到 0 把左邊界設定為 0

left =

0# 為了照顧到 1 把右邊界設定為 x // 2 + 1

right = x //2+

1while left < right:

# 注意:這裡一定取右中位數,如果取左中位數,**可能會進入死迴圈

# mid = left + (right - left + 1) // 2

mid =

(left + right +1)

>>

1 square = mid * mid

if square > x:

right = mid -

1else

: left = mid

# 因為一定存在,因此無需後處理

return left

744. 尋找比目標字母大的最小字母

給定乙個有序的字元陣列 letters 和乙個字元 target,要求找出 letters 中大於 target 的最小字元,如果找不到就返回第 1 個字元。

示例:

輸入:

letters = ["c", "f", "j"]

target = "a"

輸出: "c"

輸入:letters = ["c", "f", "j"]

target = "c"

輸出: "f"

輸入:letters = ["c", "f", "j"]

target = "k"

輸出: "c"

解法

二分法

class solution:

def nextgreatestletter(self, letters: list[str], target: str) -> str:

l, h = 0, len(letters) - 1

while l < h:

m = (l + h) // 2

if letters[m] > target:

h = m

else:

l = m + 1

return letters[l] if letters[l] > target else letters[0]

沒二分法:

class solution:

def nextgreatestletter(self, letters: [str], target: str) -> str:

for i, j in enumerate(letters):

if target < j:

return j

else:

return letters[0]

540. 有序陣列中的單一元素

給定乙個只包含整數的有序陣列,每個元素都會出現兩次,唯有乙個數隻會出現一次,找出這個數。

示例

輸入: [1,1,2,3,3,4,4,8,8]

輸出: 2

輸入: [3,3,7,7,10,11,11]

輸出: 10

解法

令 index 為 single element 在陣列中的位置。在 index 之後,陣列中原來存在的成對狀態被改變。如果 m 為偶數,並且 m + 1 < index,那麼 nums[m] == nums[m + 1];m + 1 >= index,那麼 nums[m] != nums[m + 1]。

從上面的規律可以知道,如果 nums[m] == nums[m + 1],那麼 index 所在的陣列位置為 [m + 2, h],此時令 l = m + 2;如果 nums[m] != nums[m + 1],那麼 index 所在的陣列位置為 [l, m],此時令 h = m。

class

solution

:def

singlenonduplicate

(self, nums:

[int])

->

int:

l =0 h =

len(nums)-1

while l < h:

m = l +

(h - l)//2

if m %2==

1:m -=

1if nums[m]

== nums[m +1]

: l = m +

2else

: h = m

return nums[l]

278. 第乙個錯誤的版本

題目描述:給定乙個元素 n 代表有 [1, 2, …, n] 版本,在第 x 位置開始出現錯誤版本,導致後面的版本都錯誤。可以呼叫 isbadversion(int x) 知道某個版本是否錯誤,要求找到第乙個錯誤的版本。

示例:

給定 n = 5,並且 version = 4 是第乙個錯誤的版本。

呼叫 isbadversion(3) -> false

呼叫 isbadversion(5) -> true

呼叫 isbadversion(4) -> true

所以,4 是第乙個錯誤的版本

解法

如果第 m 個版本出錯,則表示第乙個錯誤的版本在 [l, m] 之間,令 h = m;

否則第乙個錯誤的版本在 [m + 1, h] 之間,令 l = m + 1。

class

solution

:def

firstbadversion

(self, n)

: l =

1 h = n

while lm = l +

(h-l)//2

if isbadversion(m)

: h = m

else

: l = m +

1return l

153. 尋找旋轉排序陣列中的最小值

34. 在排序陣列中查詢元素的第乙個和最後乙個位置

給定乙個按照公升序排列的整數陣列 nums,和乙個目標值 target。找出給定目標值在陣列中的開始位置和結束位置。

你的演算法時間複雜度必須是 o(log n) 級別。

如果陣列中不存在目標值,返回 [-1, -1]。

示例

LeetCode 查詢 二分查詢

給定乙個 n 個元素有序的 公升序 整型陣列 nums 和乙個目標值 target 寫乙個函式搜尋 nums 中的 target,如果目標值存在返回下標,否則返回 1。示例 輸入 nums 1,0,3,5,9,12 target 9 輸出 4 解釋 9 出現在 nums 中並且下標為 4 輸入 nu...

leetcode 二分查詢

leetcode 29 給定兩個整數,被除數dividend和除數divisor。將兩數相除,要求不使用乘法 除法和 mod 運算子。返回被除數dividend除以除數divisor得到的商。演算法設計 用2進製的左移操作,每次對被除數左移1位,比較除數與被除數左移的後的大小關係,並在結果中加上左移...

leetcode 二分查詢

二分查詢基本實現 public intbinarysearch int nums,int key return 1 變種二分查詢,找出陣列中key重複元素最左位置 注意邊界 public intbinarysearch int nums,int key if nums l key return l ...