目录
二分查找
1.什么是二分查找?为什么要用二分查找?
二分查找也叫做折半查找。
相当于将容器反复折成一半,然后查找当中的元素,对于数据比较多的时候,这样的查找形式相较于从头遍历一个一个查找效率更高。
2.二分查找的适用情况
数组中的元素必须是有大小顺序的,即从小到大,或者从大到小。同时数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的。
如果是无序的,也可以先进行排序。但是排序之后,会改变原有数据的顺序,查找出来元素位置跟原来的元素可能是不一样的,所以排序之后再查找只能判断当前数据是否在容器当中,返回的索引无实际的意义。
3.二分查找的实现原理简要描述
假设要查找的数据在数组中存在,则将要查找的数据和数组中间节点的元素进行大小比较,比较完之后有以下几种情况:
-
要查找的数据和中间节点的数据相等:说明找到了
-
要查找的数据比中间节点的数据小:说明要查找的数字在中间节点左边,将容器折半继续查找
-
要查找的数据比中间节点的数据大:说明要查找的数字在中间节点右边,将容器折半继续查找
4.二分查找图示
自己做了一个简陋的示意图。
我们定义 target 是在一个在左闭右闭的区间里,也就是[min, max] 。
5.二分查找的代码实现
public class Demo {
public static void main(String[] args) {
//需求:定义一个方法binarySearch利用二分查找,查询某个元素在数组中的索引
int[] arr = {1, 4, 9, 16, 16, 19, 33};
System.out.println(binarySearch(arr, 19));
}
public static int binarySearch(int[] arr, int number){
//1.定义两个变量记录要查找的索引的范围
int min = 0;
int max = arr.length - 1;
//2.利用循环不断的去找要查找的数据。循环的两个结束条件:1、找到了数据,返回-1;2、没有找到数据,min > max,返回下标
while(true){
if(min > max){
return -1;
}
//3.找到min和max的中间位置
int mid = (min + max) / 2;
//4.拿着mid指向的元素跟要查找的元素进行比较
if(arr[mid] > number){
//number在mid的左边
//min不变,max = mid - 1;
max = mid - 1;
}else if(arr[mid] < number){
//number在mid的右边
//max不变,min = mid + 1;
min = mid + 1;
}else{
//number跟mid指向的元素一样
//找到了
return mid;
}
}
}
}
6.刷一道Leetcode原题
这里参考代码随想录的解答:
对于左闭右闭区间:
class Solution {
public int search(int[] nums, int target) {
// 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid - 1;
}
return -1;
}
}
对于左闭右开区间:
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length;
while (left < right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid;
}
return -1;
}
}