美文网首页算法第四版习题讲解
算法练习(63): 修改二分查找算法(1.4.10)

算法练习(63): 修改二分查找算法(1.4.10)

作者: kyson老师 | 来源:发表于2017-12-11 20:36 被阅读105次

本系列博客习题来自《算法(第四版)》,算是本人的读书笔记,如果有人在读这本书的,欢迎大家多多交流。为了方便讨论,本人新建了一个微信群(算法交流),想要加入的,请添加我的微信号:zhujinhui207407 谢谢。另外,本人的个人博客 http://www.kyson.cn 也在不停的更新中,欢迎一起讨论

算法(第4版)

知识点

  • 二分查找

题目

1.4.10 修改二分查找算法,使之总是返回和被查找的键匹配的索引最小的元素。(且仍能够保证对数级别的运行时间)


1.4.10 Modify binary search so that it always returns the element with the smallest index that matches the search element (and still guarantees logarithmic running time).

分析

稍加思考,我们不难写出如下代码

public int rank(int key, int[] a) { // 数组必须是有序的
      int lo = 0;
      int hi = a.length - 1;
      while (lo <= hi) { // 被查找的键要么不存在,要么必然存在于a[lo..hi]之中
            int mid = lo + (hi - lo) / 2;
            if (key < a[mid])
                  hi = mid - 1;
            else if (key > a[mid])
                  lo = mid + 1;
            else{
                  // 先向左边查找,但要注意避免越界
                  int minIndex = mid;
                  while (a[minIndex] == key) {
                        --minIndex;
                        if (minIndex < 0) {
                              break;
                        }
                  }
                  return minIndex+1;
            }

      }           

      return -1;
}

并且我们可以写个测试用例

int[] b = { 1, 2, 3, 5, 4, 5, 6, 77, 7, 8, 8, 9, 1, 11, 22, 234, 90 };
Arrays.sort(b);
BinarySearch search = new BinarySearch();

int targetKey = 1;
int index = search.rank(targetKey,b);
System.out.println(targetKey + "在第"+index+"个");

这里顺便列举网上的一些错误的方式,例如

else {
    while(mid>0&&a[--mid]==key);  //该语句排除了左边与之相同的值
    return mid+1;
}

这一段明显是有问题的,本测试用例就可以反驳,当targetKey为1的时候,错误的方式算出来的是1,其实是0。

接下来我们接着分析。

上面我们的解法是不是对的呢,只能说大部分情况下没问题,但这里给出一个极端的情况

int[] b = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };

这里,时间复杂度就不是对数了,我们需要重新考虑解决方案。
这里有个很简洁的解决方案:find lowest index of a given value in a presorted array 大家可以看看,笔者的答案就是基于这个解法的。

大概的思路就是,原来的if (a[mid] < key)else if (a[mid] > key)不变,而是变if (a[mid] == key)。当if (a[mid] < key)满足后,再去看它前面的一个元素是否也满足,即a[mid-1] == key,当然,为了避免越界,我们要先加mid > 0的判断。

答案

public int rank(int[] a, int key) {
      int hi = a.length;
      int lo = 0;
      int mid = 0;
      while(lo < hi){
            mid = (hi + lo) / 2;
            if (a[mid] < key) {
            lo = mid + 1;
            }else if (a[mid] > key) {
            hi = mid;
            }else if (mid > 0 && a[mid-1] == key) {
            hi = mid;
            }else {
                  return mid;
            }
      }
      
      return -1;
}

代码索引

BinarySearch_ON.java

BinarySearch_OlogN.java

广告

我的首款个人开发的APP壁纸宝贝上线了,欢迎大家下载。

相关文章

  • 算法练习(63): 修改二分查找算法(1.4.10)

    本系列博客习题来自《算法(第四版)》,算是本人的读书笔记,如果有人在读这本书的,欢迎大家多多交流。为了方便讨论,本...

  • 数据结构与算法系列——二分查找

    二分查找算法的简单介绍 今天我们来学习一下二分查找算法,也叫做折半查找算法。使用二分查找算法的前提是数据需要是有序...

  • 算法

    一.算法基础--算法的特性 二.算法基础--算法的复杂度 三.顺序查找和二分查找 顺序查找 二分查找(前提是有序的...

  • 『算法』『数据结构』 浅谈二分算法,理解程序员必懂必会的计算机常

    基本认识 二分算法,又名二分查找、折半查找,是一种查找算法,是最基础的,最简单易学且高效实用的算法之一。二分算法的...

  • 数据结构和算法--二分查找

    二分查找 二分查找的思想 二分查找(Binary Search)算法,也叫折半查找算法。 二分查找针对的是一个有序...

  • 15-二分查找(上):如何用最省内存的方式实现快速查找功能?

    一种针对有序数据集合的查找算法:二分查找(Binary Search)算法,也叫折半查找算法。 二分查找针对的是一...

  • 二分查找算法

    一、二分查找算法 二分查找算法又称为折半查找算法,它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序...

  • 算法-二分搜索算法

    算法:二分搜索算法(折半查找算法)时间复杂度: 二分搜索算法概述 二分搜索算法伪代码 二分搜索算法实现 二分搜索算...

  • 刷题笔记

    算法思想 一、二分查找 1. 算法思想 算法详解 算法细节 一定要看二分查找细节.md 实现时需要注意以下细节: ...

  • 二分查找算法

    @(算法集) 二分查找算法 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,...

网友评论

    本文标题:算法练习(63): 修改二分查找算法(1.4.10)

    本文链接:https://www.haomeiwen.com/subject/lsewixtx.html