前言
二分查找(又称折半查找)是一种查找效率十分高的算法,仅适用于有序的顺序表。下面结合我个人的理解为大家讲述一下二分查找算法的思路,希望对大家有所帮助。
一、二分查找的思路
二分查找算法的思路顾名思义,就是将一个有序的顺序表通过设置middle指针一分为二,然后通过判断查找目标target与nums[middle]的大小,不断地对这个有序的顺序表进行一分为二的操作,直到查找到目标target或者查找不到目标target之后,这个算法就会结束。
二、一个例子
1.图例
如下图所示,在这里我定义了一个数组nums,数组的长度length=11,我们要查找的目标target为33,简单的用眼睛扫一下,我们可以看到查找目标target是存储在数组下标为7的地方,也就是nums[7]。我们定义了三个指针,分别为left=0,middle=left+(right-left)/2,right=length-1。在算法的开始,三个指针分别停留在这三个位置,然后我们比较可以得到:nums[middle]<target,这时,可以确定33一定在middle的右边,也就意味着左半部分的搜索区间中一定不会存在33,因此我们可以将左半区给舍弃,让left=middle+1,在这里也体现了二分,所谓二分就是将区间一分为二,舍弃掉不需要的半区。
让left=middle+1之后,right保持不变,通过:middle=left+(right-left)/2计算出middle新的位置,如下图所示
同样的思路,我们比较可以得到:nums[middle]>target,这时,可以确定33一定在middle的左边,也就意味着右半部分的搜索区间中一定不会存在33,因此我们可以将右半区给舍弃,让right=middle-1,然后计算出三个指针新的位置,如下图
比较可以得到:nums[middle]<target,舍弃左半区,left=middle+1,然后计算出三个指针新的位置,如下图
查找成功之后,我们返回middle的值,整个算法到此结束。
2.代码实现
class Solution {
public int search(int[] nums, int target) {
int left = 0; //初始化left
int right = nums.length - 1; //初始化right
while(left <= right){ //进入循环的条件
int middle = left+(right-left)/2 ; //防止right过大导致溢出
if(nums[middle] > target){ //target在左半区
right = middle - 1;
}
else if(nums[middle] < target){ //target在右半区
left = middle + 1;
}
else //nums[middle]==target
return middle;
}
return -1; //查找不成功返回-1
}
}
总结
实现二分查找并不难,需要注意的是坚持循环不变量的原则。本文是对左闭右闭区间即[left,right]的代码实现。大家看完之后可以自己尝试着实现一下[left,right)的二分查找。