二分查找及其变种问题
基本的二分查找
代码实现
非递归版本
#include<stdio.h>
int binary_search(int a[], int low,int high,int val)
{
int mid;
while(low<=high)
{
mid = low + high / 2;
if(a[mid]>val)
{
high = mid - 1;
}else if(a[mid]==val)
{
return mid;
}else
{
low = high + 1;
}
}
return -1;
}
int main()
{
int a[5] = {1, 3, 5, 7, 9};
printf("%d", binary_search(a, 0, 4, 5));
}
递归版本
#include <stdio.h>
int binary_search(int a[], int low, int high, int val)
{
int mid;
if (low <= high)
{
mid = low + high / 2;
if (a[mid] > val)
{
return binary_search(a, low, mid - 1, val);
}
else if (a[mid] == val)
{
return mid;
}
else
{
return binary_search(a, mid + 1, high, val);
}
}
if(low>high)
{
return -1;
}
}
int main()
{
int a[5] = {1, 3, 5, 7, 9};
printf("%d", binary_search(a, 0, 4, 10));
}
二分查找比较简单就不再赘述。
变种问题
查找第一个等于给定值的元素
过程描述
普通的二分查找只能保证找到给定值元素的位置,并不能保证位置唯一或者出现的顺序,通过改变二分查找的代码部分内容,可以实现。
当我们a[mid]=val的时候,此时我们就可以通过判断mid前面一位的元素是否也为给定值,如果是的话,那就将high移动到mid前一位(图上情况是正好只有mid前一位为指定值,实际上a[1]也可能为给定值),在low和high(mid-1)之间再次二分查找。如果mid前一位元素不等于给定值,说明mid就是第一次出现的位置(因为这是个有序的数组,前面一位如果不等于的话,那就一定小于给定值)
代码实现
#include<stdio.h>
int binary_search(int a[], int low,int high,int val)
{
int mid;
if(low<=high)
{
mid = low + high / 2;
if(a[mid]>val)
{
binary_search(a, mid + 1, high, val);
}else if(a[mid]==val)
{
if (a[mid - 1] == val)
{
return binary_search(a, low, mid - 1, val);
}
return mid;
}else
{
high = mid - 1;
return binary_search(a, low, mid-1, val);
}
}
if(low>high)
{
return -1;
}
}
int main()
{
int a[6] = {1, 2, 3, 3, 3, 5};
printf("%d", binary_search(a, 0, 5, 3));
}
查找最后一个等于给定值的元素
过程描述
理解了第一种变体,这一种就很好理解了,就不做过多解释。
代码实现
#include<stdio.h>
int binary_search(int a[], int n,int val)
{
int low = 0;
int high = n - 1;
int mid = 0;
while(low<=high)
{
mid = (low + high) / 2;//记得打括号还可以转化成别的两种写法1.high-(high-low)/2
if(a[mid]>val) //2.low + ((high - low) >> 1).可以加快运行速度,防止溢出
high = mid - 1;
else if(a[mid]==val)
{
if((a[mid+1]!=val)||(mid==n-1))
{
return mid;
}else
{
low = mid + 1;
}
}else
{
low = mid + 1;
}
}
return -1;
}
int main()
{
int a[6] = {1, 2, 3, 3, 3, 5};
printf("the last position:%d", binary_search(a, 6,3));
}
查找第一个大于等于给定值的元素
过程描述
对于这种进行一下解释。如图所示。
代码实现
#include<stdio.h>
int binary_search(int a[], int n,int val)
{
int low = 0;
int high = n - 1;
int mid = 0;
while(low<=high)
{
mid = (low + high) / 2;
if(a[mid]<val)
{
low = mid + 1;
}else
{
if(a[mid-1]<val||mid==0)
{
return mid;
}else
{
high = mid - 1;
}
}
}
return -1;
}
int main()
{
int a[6] = {1, 2, 3, 3, 3, 5};
printf("the last position:%d", binary_search(a, 6,4));
}
查找最后一个小于等于给定值的元素
过程描述
理解了上述图片,这个就不需要多余赘述了,可以自己推理一下检验一下是否掌握了
代码实现
#include<stdio.h>
int binary_search(int a[], int n,int val)
{
int low = 0;
int high = n - 1;
int mid = 0;
while(low<=high)
{
mid = (low + high) / 2;
if(a[mid]<=val)
{
if(a[mid+1]>val ||mid==n-1 )
{
return mid;
}else{
low = mid + 1;
}
}else
{
high = mid - 1;
}
}
return -1;
}
int main()
{
int a[6] = {1, 2, 3, 3, 3, 5};
printf("the last position:%d", binary_search(a, 6,4));
}