zoukankan      html  css  js  c++  java
  • 数据结构与算法--二分搜索(binary search)

    前言

    之前面试准备秋招,重新翻起了《编程之美》。在第三章节看到了一道关于二分搜索的讨论,觉得有许多细节是自己之前也没怎么特别注意地方,比如二分搜索的初始条件,转化、终止条件之类的。

    问题

    找出一个有序(字典序)字符串数组 arr 中值等于字符串v的元素的序号,如果有多个元素满足这个条件,则返回其中序号最大的。
    

    分析

    如果去掉“返回序号最大的”,则标准的二分解法。但是数据中有重复元素,要求返回序号序号最大的元素序号。

    以下是有BUG的解法:

    
    int bisearch(int** arr, int b, int e, int* v)
    {
        int minIndex = b, maxIndex = e, midIndex;
        while(minIndex < maxIndex)
        {
            midIndex = (minIndex + maxIndex) / 2;
            if(strcmp(arr[midIndex], v) <=0)
                midIndex = minIndex;
            else
                midIndex = maxIndex - 1;
        }
        if(!strcmp(arr[maxIndex], v))
            return maxIndex;
        else
            return -1;
    }
    
    • 可能存在上溢出
    midIndex = (minIndex + maxIndex) / 2;
    

    咋一眼看去没什么大的问题,但是极端情况下可能导致错误。如果这是个32位的程序,32位有符号整数可以标识的范围-2^31 ~ 2^31,如果minIndex+maxIndex恰好超过了2^32,就会导致上溢出,此时midIndex变成负数。

    想象一下,当minIndex=2, maxIndex=3, 而arr[minIndex] <= v时,midInde将始终等于minIndex,进入死循环。

    正确解法

    int bisearch(int** arr, int b, int e, int* v)
    {
        int minIndex = b, maxIndex = e, midIndex;
        while(minIndex < maxIndex - 1)
        {
            midIndex = minIndex + (maxIndex - minIndex) / 2;
            if(strcmp(arr[midIndex], v) <=0)
                midIndex = minIndex;
            else
                midIndex = maxIndex;
        }
        if(!strcmp(arr[maxIndex], v))
            return maxIndex;
        else if(!strcmp(arr[maxIndex], v))
            return minIndex;
    else:
            return -1;
    }
    

    扩展问题

    给定一个有序(不降序)数组arr:

    • 求任意一个使得arr[i]等于v,不存在则返回-1
    • 求最小的i使得arr[i]等于v,不存在则返回-1
    • 求最大的i使得arr[i]等于v,不存在则返回-1
    • 求最大的i使得arr[i]小于v,不存在则返回-1
    • 求最小的i使得arr[i]大于v,不存在则返回-1
  • 相关阅读:
    [转]读取并修改App.config文件
    [转]线程和进程的概念
    实习日志(3)
    实习日志2
    实习小感,回学校啦~~~~
    请教LUA高手一段代码,希望帮忙谢谢!
    实习的日子
    vs显示 error LNK2019: 无法解析的外部符号 _main解决办法
    创建一个新窗口进程并返回进程ID号和进程的主线程ID号
    显示基本图形界面第一天
  • 原文地址:https://www.cnblogs.com/CocoML/p/12727384.html
Copyright © 2011-2022 走看看