题目描述
使用递归算法,实现二分搜索。
输入
多组数据输入,每组第一个数字为数组的长度n,然后输入n个整数,最后输入待查询的值。
输出
输出待查询值所在的位置,如果没有找到,则返回-1。
样例输入
3 1 2 3 2
4 0 1 3 4 2
样例输出
2
-1
思路:其实递归与非递归的思路基本一致,都是先中间再两边,找到了就返回元素下标,没找到就继续缩小区间,直到找到为止,详细思路我会注释在代码里面,如有不对,欢迎各位大佬指出。
递归代码
#include <bits/stdc++.h>
using namespace std;
int a[100000];
int digui(int k, int left, int right)
{
int mid = left + ((right - left) >> 1);
// int mid = (left + right) / 2;
//mid=(left+right)/2 等价于 left+(right-left)/2,这样写能防止right+left溢出,写为位运算
//mid=left+((right-left)>>1)的形式更高效,由于位运算的优先级低于逻辑运算,所以要在多项式中的位运算上加上小括号,不然程序就会错误
//注意:left一定要写在前面,写在后面的话右移的位数就是(left+1)
if (left <= right)
{
//以下内容读者可以手动模拟一遍
if (a[mid] == k) //如果找到了就返回数组下标对应值
return mid;
if (a[mid] > k) //如果所要找的k值在右边,就继续递归右边区间(区间缩小一半)
return digui(k, left, mid - 1);
else //否则就递归左边区间
return digui(k, mid + 1, right);
}
return -1; //如果没找到就返回题目要求的-1
}
int main()
{
int n, k;
while (cin >> n)
{
for (int i = 1; i <= n; ++i)
cin >> a[i];
cin >> k;
//这里一定要注意,这是要找K值,所以k一定要作为参数放入函数,否则函数就不能正常运行
cout << digui(k, 1, n) << endl;
}
return 0;
}
非递归代码
#include <bits/stdc++.h>
using namespace std;
int a[100000];
int digui(int k, int n)
{
int left = 1, right = n;//分别让left与right等于数组左右两边界
while (left <= right)
{
int mid = (right + left) / 2;//建议使用上述的位运算,位运算能够大大提高程序的效率
if (a[mid] == k)
return mid;
else if (k > a[mid])
left = mid + 1;//区间减半,下同
else
right = mid - 1;
}
return -1;
}
int main()
{
int n, k;
while (cin >> n)
{
for (int i = 1; i <= n; ++i)
cin >> a[i];
cin >> k;
cout << digui(k, n) << endl;
}
return 0;
}
二分搜索升级版
题目描述
设a[0:n-1]是已排好序的数组。请改写二分搜索算法,使得当待搜索元素x不在数组中时,返回小于x的最大元素的位置i和大于x的最小元素的位置j;当待搜索元素x在数组中时,返回的i和j相同,均为x在数组中的位置
输入
多组数据输入,每组第一个数字为数组的长度n,然后输入n个整数,最后输入带查询的值x。
输出
输出小于x的最大元素的位置i和大于x的最小元素的位置j;当待搜索元素x在数组中时,返回的i和j相同,均为x在数组中的位置
样例输入
3 1 2 3 2
4 0 1 3 4 2
样例输出
2 2
2 3
这个题目稍微比上面的难一点,不过实现的过程依然是上述的思想
#include <bits/stdc++.h>
using namespace std;
int a[100000];
int pos1, pos2, n, x;
void search(int l, int r, int x)
{
if (l > r) //递归结束条件之一
{
//如果此时左边大于右边,那么大于k值得是左边所对应的元素值,当然小于K值得就是右边对应的元素值
pos1 = r, pos2 = l;
return;
}
int mid = (l + r) / 2; //建议使用位运算
if (a[mid] == x) //递归结束条件之二
{
pos1 = pos2 = mid;
return;
}
else if (a[mid] > x)
search(l, mid - 1, x); //递归左边
else
search(mid + 1, r, x); //递归右边
}
int main()
{
while (cin >> n)
{
for (int i = 1; i <= n; ++i)
cin >> a[i];
cin >> x;
int l = 1, r = n; //让他们分别为数组左右两端点的下标值
search(1, n, x); //调用函数
cout << pos1 << ' ' << pos2 << endl;
}
return 0;
}
只要是靠努力的话,天才也是可以被打败的 |
---|