二分查找是一個非常常用且簡潔的查找算法,相信很多人也知道它的時間復雜度是logN,但是我看網上的大多數博客給出的所謂推導過程都十分不嚴謹,於是我花了些時間自己寫了推導過程。
首先上二分查找的代碼:
public int find(int x, int[] data) { return find(x, data, 0, data.length - 1); } /** * 查找元素下標,沒找到返回-1 * @param x 待查找元素 * @param data 有序的元素數組 * @createTime:2017年3月4日 * @author: gaojiabao */ private int find(int x, int[] data, int low, int high) { int mid = (low + high) >> 1; if (x == data[mid]) { return mid; } else if (x > data[mid]) { low = mid + 1; } else if (x < data[mid]) { high = mid - 1; } if (low == high) { if (x == data[low]) { return low; } else { return -1; } } else { return find(x, data, low, high); } }
下面是推導過程:
假設數據的規模為N(即每次調用時的high-low),程序執行的比較次數表示為C(N),假設程序查找的是一個不存在的數據,則此時執行的次數是最多的:
執行第一次時,有:
1代表執行了一次x和data[mid]的比較過程,代表下一次遞歸調用find方法時high-low的值,也就是新的數據規模每次較少一半以上。
遞歸上面的公式,有:
我們知道每一個整數都可以表示為2i+k的形式,如1=20+0,5=22+1,10=23+2,因此
設N=2i+k
令上面公式的n=i,則有:
因為N=2i+k,則有i=⌊lgN⌋,因此:
因為我們一直以來的假設是要查找到的元素是找不到的,所以現在的情況是C(N)最大的情況,對於一般情況,則有:
因此二分查找的時間復雜度是logN。