赞
踩
二分查找也称折半查找,是一种效率较高的查找方式。但是,二分查找要求线性表为顺序存储结构且表按关键字有序排列。
时间复杂度:O(log2n)
便于叙述,笔者以数组array[N] = [1,10,20,30,99,1020]为例。left、right分别表示数组的左界和右界。需要查找的值记为value。
假设我们需要查找数值99,mid首先指向的位置应为20的位置。left指向1,right指向1020。判断array[mid] = 20 与 99 不相等,此时,left = mid + 1,右移;right 不变;mid更新为4。此时,array[mid] = 99, 查找成功,返回索引值4。
何时递归结束???
public class BinarySearch { public static void main(String[] args) { int[] array = {1,10,20,30,99,1020}; // 待查找值设置为99 、 0 int value1 = 99; int value2 = 0; System.out.println(value1 + "'s index: " + bs(array,0,array.length-1,value1)); System.out.println(value2 + "'s index: " + bs(array,0,array.length-1,value2)); } // 二分查找递归实现 /** * * @param array 数组 * @param left 左端点 * @param right 右端点 * @param value 待查找的值 * @return 查找到value则返回索引值;否则返回-1 */ public static int bs(int[] array, int left, int right, int value) { // 没有找到 if(left > right){ return -1; } int mid = (left + right) / 2; if(value > array[mid]){ // 向右查找,更新left = mid + 1 return bs(array, mid + 1, right, value); }else if(value < array[mid]){ // 向左查找,更新right = mid - 1 return bs(array, left, mid - 1, value); }else { return mid; } } }
非递归的方法体如下,具体见注释:
/** * * @param array 数组 * @param value 待查找的值 * @return 查找到value则返回索引值;否则返回-1 */ public static int binarySearch(int[] array, int value){ int left = 0; int right = array.length - 1; // 只要left <= right 就一直查找 while (left <= right){ int mid = (left + right) / 2; // mid放在循环内声明是因为mid也需要更新 if(value > array[mid]){ // 向右查找,更新left = mid + 1 left = mid + 1; }else if(value < array[mid]){ // 向左查找,更新right = mid - 1 right = mid - 1; }else { return mid; } } // 出了循环说明没有找到,就返回-1 return -1; }
设待查找值设置为99 、 0,在array[N] = [1,10,20,30,99,1020]中查找。运行结果如下(99在数组内,故返回索引4;0不在数组中,故返回-1)
这一部分,我们以递归方式实现的代码优化为例,思路如下:
取示例array[N] = {1,10,20,30,99, 99, 99, 1020},我们需要查找99
优化代码如下:
import java.util.ArrayList; public class BinarySearch { public static void main(String[] args) { int[] array = {1,10,20,30,99, 99, 99, 1020}; // 待查找值设置为99 、 0 int value1 = 99; int value2 = 0; System.out.println(value1 + "'s index: " + bs(array,0,array.length-1,value1)); System.out.println(value2 + "'s index: " + bs(array,0,array.length-1,value2)); } // 二分查找递归实现 /** * * @param array 数组 * @param left 左端点 * @param right 右端点 * @param value 待查找的值 * @return 查找到value则返回索引值;否则返回空集合 */ public static ArrayList<Integer> bs(int[] array, int left, int right, int value) { // 没有找到 if(left > right){ return new ArrayList(); } int mid = (left + right) / 2; if(value > array[mid]){ // 向右查找,更新left = mid + 1 return bs(array, mid + 1, right, value); }else if(value < array[mid]){ // 向左查找,更新right = mid - 1 return bs(array, left, mid - 1, value); }else { ArrayList<Integer> res = new ArrayList<>(); // 扫描左侧 int index = mid - 1; while (true){ if(index < 0 || array[index] != value){ break; } res.add(index); index--; } // mid记录一次 res.add(mid); // 扫描右侧 index = mid + 1; while (true){ if(index > array.length - 1 || array[index] != value){ break; } res.add(index); index++; } return res; } } }
取示例array[N] = {1,10,20,30,99, 99, 99, 1020},我们查找99、0,应该返回4、5、6和空。
— end
本文到此就结束啦,如果对你有帮助,顺手点个赞叭!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。