二分搜索

对于一个有序序列,我们可以用二分搜索的方式在该序列中搜索某个数值。

以升序序列为例,二分搜索首先确定搜索的范围(即搜索序列的第一个元素的位置 left 和最后一个元素的位置 right),然后计算出中间位置 mid。比如我们要搜索的序列是:2, 7, 11, 19, 23, 31, 33, 39。在初始的状态下,搜索范围是整个序列,那么第一个元素的位置left就是1,最后一个元素的位置right就是8,mid = (left + right)/2 = 4(注意序列的长度是偶数,left+right的和是奇数,这里对结果进行了向下取整)。

接下来,检查中间位置的元素是否是要搜索的值 target(假设我们要搜索的值是31,那么target就等于31),如果不是,则比较中间元素与 target 的大小关系:如果中间位置的元素比target大,因为序列是升序的,所以 target 只可能在中间元素的左侧,也就是位于 left 和 mid - 1之间,此时把 right 更新为 mid - 1,也就是说,下一次我们要搜索的范围的右边界发生了变化。更新right后,再次计算新的mid,重复上面的搜索过程;如果中间位置的元素比 target 小,那么 target 只可能位于 mid + 1 和 r 之间,此时把 l 更新为 mid + 1(这种情况是左边界发生了变化)后,重复上面的搜索过程。

在搜索过程中,一旦发现某一次,搜索范围中间的值等于target,那么就是找到了目标值;或者始终找不到的情况下,当left > right的时候,我们就知道target不在我们搜索的序列中,此时搜索也就结束了。

以在序列(2, 7, 11, 19, 23, 31, 33, 39)中搜索31为例,说明一下二分搜索的流程。
第一轮搜索:left = 1,right = 8(注意在大多数编程语言中,数组下标是从0开始的),mid = (1 + 8) / 2 = 4,序列中第四个元素是19,19小于要搜索的目标值31,因此31只可能在序列的后半段,此时更新左侧边界left,把left赋值为mid + 1,此时left变成了5;
第二轮搜索:left = 5,right = 8,mid = (5 + 8) / 2 = 6,序列中第6个元素是31,此时找到了目标元素,其在序列中的位置是6,搜索结束。

再以要搜索的值是30为例,我们从刚才的第二轮搜索继续。到了上面的第二轮搜索,序列中第6个元素是31,大于30,那么30只可能存在于第5个元素(left的值为5)的右侧、31(第6个元素)的左侧,此时更新right,将其赋值为mid - 1,此时right变成了5。继续进行第三轮搜索。
第三轮搜索:left = 5,right = 5,mid = (5 + 5) / 2 = 5。序列中第5个元素是23,小于30,此时更新left为mid + 1,left的值变为6,继续进行第四轮搜索。
第四轮搜索:在进行搜索前,发现left的值已经大于right,这时可以确定要搜索的值不在序列中,搜索结束。

#include
# include 
using namespace std;

int main() {
    int n;
    cin >> n;
    vector nums(n);
    for (int i = 0; i < n; i++) {
        cin >> nums[i];
    }
    int V;
    cin >> V;

    int left = 0, right = n - 1;
    int pos = -1;
    while (left <= right) {
        int mid = (left + right) / 2;
        if (nums[mid] == V) {
            pos = mid + 1;  // 位置从1开始编号,所以加1
            break;
        } else if (nums[mid] < V) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    if (pos != -1) {
        cout << pos << endl;
    } else {
        cout << "Value not found." << endl;
    }

    return 0;
}
全部评论

相关推荐

截止11.9大概11.5收到了小米汽车南京的安卓开发offer,薪资的话叠加小米+南京两层buff,其实可想而知,不高不低吧,考虑到本身也不需要鼠鼠我挣大钱养家and南京生活成本低且离家近,所以还是可以接受的。问题在于安卓开发的话,虽说安卓在客户端里算是泛用性比较广的,但是本身需求小,都说和测开坐一桌但是实际需求量可能甚至不如测开,从未来长期发展来讲有点担忧。虾皮二面已挂,遗憾退场;腾讯pcg客户端捞起来面了一轮然后杳无音信,遗憾退场;中科创达,腾讯云智等等后续流程已拒,主要是考虑到这些厂工资实在低且地点也不满意。合肥科大讯飞,北京滴滴仍在池子里,科大讯飞这个厂就中规中矩吧,也没啥特别的想法;滴滴本身风评不错,业务也说得过去,不知道能不能泡出来,其实个人感觉泡出来也是大白菜,因为二面发挥其实一般般,不算满意。至于后续的选择,因为小米只有5天考虑时间,所以先签了;个人挺喜欢滴滴这个厂的,给我开多少都无所谓了,秋招两个月下来已经彻底被磨平棱角,感觉有口饭吃就够了,问题在于个人对北京印象不好,如果真选择了北京的话精神状态会很差。。。(且离家人朋友对象都很远),但是又对客户端的前景比较悲观,所以现在处于一个半死微活的状态,不知牛友们有无高见。发文时鼠鼠正处于去香港的路上,想去散散心吧,实在是太累了,后续可能会更一条秋招体验帖,讲一讲秋招的感受和自己踩的雷,让各位佬看个乐呵。哦对了,字节又给我捞起来面了,我真想啸啊
我的秋招“寄”录
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务