目录
折半查找法又称二分查找法,这种方法对于查找的列表有两个要求:
- 必须采用顺序存储结构
- 必须按关键字大小有序的排列
算法思想:
首先,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;
否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
实现过程:
举例:列表中有11个元素(6,12,15,18,22,25,28,35,46,58,60),给出使用折半查找法查找12的过程。
算法描述:
int BinSearch(int *nums,int numsSize,int key)
{
int low=0;
int high=numsSize-1;
while(low<=high)
{
int mid=(high+low)/2;
if(nums[mid]==key)
{
return mid;
}
if(nums[mid]<key)
{
low=mid+1;
}
else
high=mid-1;
}
return -1;
}
算法分析:
容易看出,每执行一次算法的while循环,待搜索数组的大小减小一半。因此,在最坏的情况下,while循环被执行了O(logn)次。循环体内运算需要O(1)时间,因此整个算法在最坏情况下的计算时间复杂性为O(logn)。
折半查找的方法的优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
例题详解: (搜索插入位置)
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
代码实现:
int searchInsert(int* nums, int numsSize, int target) {
int left = 0, right = numsSize - 1, ans = numsSize;
while (left <= right) {
int mid = (right+left)/2;
if (target <= nums[mid]) {
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
}