咱們假設數據大小是 n,每次查找後數據都會縮小爲原來的一半,也就是會除以2。最壞狀況下,直到查找區間被縮小爲空,才中止。java
這是一個等比數列。其中 n/2^k = 1 時, k 的值就是總共縮小的次數。算法
而每一次縮小操做只涉及兩個數據的大小比較,因此,通過了 k 次區間縮小操做,時間複雜度就是 O(k)。經過 n/2^k = 1,咱們能夠求得 k= log2n,因此時間複雜度就是 O(logn)。數組
O(logn) 這種對數時間複雜度。這是一種極其高效的時間複雜度,有的時候甚至比時間複雜度是常量級 O(1) 的算法還要高效。數據結構
由於 logn 是一個很是「恐怖」的數量級,即使 n 很是很是大,對應的 logn 也很小。code
好比 n 等於2的32次方,這個數大約是42億。也就是說,若是咱們在 42 億個數據中用二分查找一個數據,最多須要比較32次。blog
大 O 標記法表示時間複雜度的時候,會省略掉常數、係數和低階。排序
對於常量級時間複雜度的算法來講, O(1) 有可能表示的是一個很是大的常量值,好比 O(1000)、 O(10000)。遞歸
因此,常量級時間複雜度的算法有時候可能尚未 O(logn) 的算法執行效率高。內存
反過來,對數對應的就是指數。指數時間複雜度的算法在大規模數據面前是無效的。class
/** * 二分法查找,非遞歸實現 * * @param arr * @param a * @return */ public static int binarySearch(int[] arr, int a) { int start = 0; int end = arr.length - 1; while (start <= end) { // 不能是start < end int mid = start + ((end - start) >> 1); //start + (end - start)/2 位運算符速度快 if (arr[mid] == a) { return mid; } else if (arr[mid] > a) { end = mid - 1; // end = min 有時會形成死循環 } else { start = mid + 1; } } return -1; }
/** * 二分法遞歸實現 * * @param arr * @param start * @param end * @param a * @return */ public static int binarySearch2(int[] arr, int start, int end, int a) { if (start > end) return -1; int mid = start + ((end - start) >> 1); if (arr[mid] == a) { return mid; } else if (arr[mid] > a) { end = mid - 1; return binarySearch2(arr, start, end, a); } else { start = mid + 1; return binarySearch2(arr, start, end, a); } }
二分查找的時間複雜度是O(logn),查找數據的效率很是高。不過,並非什麼狀況下均可以用二分查找,它的應用場景是有很大侷限性的。
首先,二分查找依賴的是順序表結構,就是數組。
二分查找針對的是有序數據。
數據量太大也不適合二分查找。