二分查詢也稱為折半查詢,每次都能將查詢區間減半,這種折半特性的演算法時間複雜度為 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 ...