二分搜尋 Binary Search

2021-10-22 23:54:27 字數 2936 閱讀 8522

複雜度

可能對應的演算法

備註o(1)

位運算常數級複雜度,一般面試中不會有

o(logn)

二分法,倍增法,快速冪演算法,輾轉相除法

o(n)

列舉法,雙指標演算法,單調棧演算法,kmp演算法,rabin karp,manacher』s algorithm

又稱作線性時間複雜度

o(nlogn)

快速排序,歸併排序,堆排序

o(n^2)

列舉法,動態規劃,dijkstra

o(n^3)

列舉法,動態規劃,floyd

o(2^n)

與組合有關的搜尋問題

o(n!)

與排列有關的搜尋問題

while的目的是縮小一半的區間

二分法基礎概念–leetcode704

class

solution

int left =

0, right = nums.length -1;

// 要點1: left + 1 < right

while

(left +

1< right)

else

if(nums[mid]

< target)

else

if(nums[mid]

> target)

}//要點5:出迴圈的時候,判斷誰是題目所要的答案

if(nums[left]

== target)

if(nums[right]

== target)

return-1

;}}

q: 要點1處為什麼要用 left + 1 < right?而不是 left < right 或者 left <= right?

a: 為了避免死迴圈。二分法的模板中,整個程式架構分為兩個部分:

通過 while 迴圈,將區間範圍從 n 縮小到 2 (只有 left 和 right 兩個點)。

在 left 和 right 中判斷是否有解。

left < right 或者 left <= right 在尋找目標最後一次出現的位置的時候,會出現死迴圈。

q: 要點2處為什麼要用 left + (right - left) / 2?而不是 (left + right) / 2?

a: 為了避免可能出現加法溢位,也就是說加法的結果大於整型能夠表示的範圍,因為這裡的/號的結果多向左取數。但是left 和 right都為正數,因此 right - left 不會出現加法溢位問題。

q: 要點3處為什麼明明可以 left = mid + 1 偏偏要寫成 left = mid?

a: 大部分時候,mid 是可以 +1 和 -1 的。在一些特殊情況下,比如尋找目標的最後一次出現的位置時,當 target 與 nums[mid] 相等的時候,是不能夠使用 mid + 1 或者 mid - 1 的。因為會導致漏掉解。那麼為了節省腦力,統一寫成 left = mid 或 right = mid 並不會造成任何解的丟失,並且也不會損失效率——log(n) 和 log(n+1) 沒有區別。

q: 要點4處為什麼不直接return mid?

a: 分成三種情況。

當查詢目標值在排序陣列中的末尾位置時候(尋找右側邊界的二分搜尋),此處需要設定為left = mid;

當只是單純的查詢乙個在排序陣列中的目標值時,則可以設定為return mid。

q: 要點5處為什麼要設定判斷?

a:該模板中,當left和right相鄰時候,就不會走while迴圈,此時target就是left和right兩個值的其中乙個,故此處做判斷。

先用arraylist倍增找到≥target的乙個區間範圍,再去用二分法找到題目所要求的target。

分成四種情況討論mid所在的位置,即波谷,波峰,上公升趨勢的某點,下降趨勢的某點

參考:演算法班筆記 第二章 二分與 logn 演算法

//迭**法 <= 

//right < target < left

intbinary_search

(int

nums,

int target)

else

if(nums[mid]

> target)

else

if(nums[mid]

== target)

}// 直接返回

return-1

;}intleft_bound

(int

nums,

int target)

else

if(nums[mid]

> target)

else

if(nums[mid]

== target)

}// 最後要檢查 left 越界的情況

if(left >= nums.length || nums[left]

!= target)

return-1

;return left;

}int

right_bound

(int

nums,

int target)

else

if(nums[mid]

> target)

else

if(nums[mid]

== target)

}// 最後要檢查 right 越界的情況

if(right <

0|| nums[right]

!= target)

return-1

;return right;

}

STL中的二分查詢(binary search)

stl中對於有序序列 vector,list等 提供了相當相當強大的二分搜尋binary search演算法。對於可以隨機訪問容器 如vector等 binary search負載度為對數級別 logn 對於非隨機訪問容器 如list 則演算法複雜度為線性。現在簡要介紹一下幾種常用的binary s...

Java 二分搜尋 二分查詢

對陣列元素進行逐個查詢顯然是費時費力的工作,我們可以使用一些方法快速地搜尋出陣列中元素的指定位置.接下來我們介紹一種方法 二分搜尋法 二分搜尋法充分利用了元素間的次序關係.基本思想 將n元素分成個數大致相同的涼拌,取arr n 2 與欲查詢的x做比較,如果 下面將採用兩種方式 遞迴 非遞迴 來展示二...

二分(二分答案 二分搜尋)與單調性

經典二分搜尋是二分空間範圍。二分答案又叫二分猜值,是二分解的值空間。其實可以統一,普通的二分搜尋也是二分答案值域 下標空間,也是猜值。二分必須滿足單調性,最直觀的,二分搜尋只能在有序陣列上進行。單調性體現在,下標和元素值是單調的,也就是 if j i 有 a j a i 一般二分答案解決的問題是最優...