C语言二分查找
1.什么是二分查找?
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
2.二分查找的两个模板
1.当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
2.当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
模板1和模板2是根据区间来划分的,用到哪个区间对应哪个mid,而区间的判断有if里的具体条件判断。
比如下题:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
提示:
你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。
我写的题解如下:
int search(int* nums, int numsSize, int target){
int l = 0,r = numsSize - 1,mid,target_num;
while(l < r)
{
mid = (l+r)/2;
if(nums[mid] >= target) r = mid;
else l = mid + 1;
}
if(nums[l] == target) target_num = l;
else target_num = -1;
return target_num;
}
if里面的check为nums[mid] >= target,所以找到该target在左半区间并且包含mid,即r = mid,相反,如果nums[mid] < target ,则 l = mid +1,不包含mid。所以使用模板1,mid = (l+r)/2.
改变if里面的值为nums[mid] <= target,则变为模板2:
int search(int* nums, int numsSize, int target){
int l = 0,r = numsSize - 1,mid,target_num;
while(l < r)
{
mid = (l+r+1)/2;
if(nums[mid] <= target) l = mid;
else r = mid - 1;
}
if(nums[l] == target) target_num = l;
else target_num = -1;
return target_num;
}
可见具体使用哪个模板,得先根据条件判断它具体区间,然后确定mid的值。