二分查找
主要针对的是“有序数组”中查找某个特定元素。
1、二分查找的思想:主要针对的是有序数组,要充分利用数组有序的特性,要是遍历查找,时间复杂度是O(n),就浪费了数组的有序性。其思想就是,每次查找对比的元素都是数组的中间元素,通过比较中间元素和目标元素的大小,进一步的缩小范围,每次比较的范围都缩小为原来的一半。可以用递归的思想来实现。
2、时间空间复杂度:时间复杂度 O(logn),空间复杂度O(1)
3、代码:
递归实现:
int binarysearch(int array[], int low, int high, int target) { if (low > high) return -1; int mid = low + (high - low) / 2; if (array[mid] > target) return binarysearch(array, low, mid - 1, target); if (array[mid] < target) return binarysearch(array, mid + 1, high, target); return mid; }
循环实现:
int bsearchWithoutRecursion(int a[], int key) { int low = 0; int high = a.length - 1; while (low <= high) { int mid = low + (high - low) / 2; if (a[mid] > key) high = mid - 1; else if (a[mid] < key) low = mid + 1; else return mid; } return -1; }
4、应用
二分查找也可以用来查找含有重复数字的排序数组的first数字或last数字。
//二分法查找第一个数字 public static int getFirstNumberIndex(int[] array, int k) { int result = -2; int start = 0; int end = array.length - 1; while (start <= end) { int mid = (start + end) / 2; //若中间数字大于k,在前半部分查找 if (array[mid] > k) { end = mid - 1; } else if (array[mid] < k) { start = mid + 1; } else if (array[mid] == k) { //用短路与去判断mid>0,防止ArrayIndexOutOfBoundsException if (mid > 0 && array[mid - 1] != k || mid == 0) { result = mid; break; } else { end = mid - 1; } } } return result; }