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
  • 相关阅读:
    Linux文件及目录查找
    英语单词independent
    英语单词omitting
    英语单词deploy
    英语单词debug
    线程
    进程
    操作系统历史
    分布式爬虫
    爬虫基础
  • 原文地址:https://www.cnblogs.com/CocoML/p/12727384.html
Copyright © 2011-2022 走看看