算法概述
二分搜索,也称折半搜索、对数搜索,是一种在有序数组中查找某一特定元素的搜索算法。
搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。
二分搜索在情况下的复杂度是对数时间,进行 O(log n)次比较操作(n在此处是数组的元素数量, O是大O记号, log 是对数)。
二分搜索使用常数空间,无论对任何大小的输入数据,算法使用的空间都是一样的。除非输入数据数量很少,否则二分搜索比线性搜索更快,但数组必须事先被排序。
示例代码
Java代码(循环)
/** * 二分查找(循环) * @param arr 数组 * @param start 头索引 * @param end 尾索引 * @param target 目标 * @return 目标索引 */ public static int binarySearchByRecursion(int[] arr, int start, int end, int target){ int result = -1; while (start <= end){ int mid = start + (end - start)/2; //防止溢位 if (arr[mid] > target) end = mid - 1; else if (arr[mid] < target) start = mid + 1; else { result = mid ; break; } } return result; }
Java代码(递归)
/** * 二分查找(递归) * @param arr 数组 * @param start 头索引 * @param end 尾索引 * @param target 目标 * @return 目标索引 */ public static int binarySearch(int[] arr, int start, int end, int target){ if (start > end) { return -1; } int mid = start + (end - start)/2; //防止溢位 if (arr[mid] > target) { return binarySearch(arr, start, mid - 1, target); } if (arr[mid] < target) return binarySearch(arr, mid + 1, end, target); return mid; }
复杂度分析
时间复杂度
折半搜索每次把搜索区域减少一半,每次查找的区间大小就是n,n/2,n/2/2,n/2/2/2,简化为n/2^k,时间复杂度也就是查找的次数k,最终的区间大小必定为1,即 n/2^k=1,所以 k=log2 n。(读作:log以2为底n的对数)
空间复杂度
O(1),常数空间,无论对任何大小的输入数据,算法使用的空间都是一样的。