算法题16 二分查找及相关题目

  二分查找思想就是取中间的数缩小查找范围,对应不同的题目变形,在取到中间数mid确定下一个查找范围时也有不同,左边界有的low=mid+1,也可能low=mid,右边界有的high=mid-1,也有可能high=mid。

对于一个排序数组来说二分查找的时间复杂度是O(logn)

1. 二分查找法

 1  int BinarySearch(int arr[],int len,int target)
 2  {
 3      if (arr==NULL||len<=0)
 4          throw std::exception("Invalid input.");
 5      int low=0,high=len-1;
 6      while(low < high)
 7      {
 8          int mid = low+(high-low)/2;
 9          if (arr[mid]>target)
10              high = mid-1;
11          else if (arr[mid]<target)
12              low = mid + 1;
13          else //find the target
14              return mid;
15      }
16      //the array does not contain the target
17      return -1;
18  }

2.二分查找之寻找边界

  这种边界的寻找分为2种:最后1个小于某数的值,低边界;第1个大于某数的值,高边界,情况不同在遍历查找时边界的调整也不同。

 1)最后1个小于某数的值

 1  int FindLastSmallerNum(int arr[],int len,int target)
 2  {
 3      if (arr==NULL||len<=0)
 4          throw std::exception("Invalid input.");
 5
 6      int low=0,high=len-1;
 7      while(low<high)
 8      {
 9          int mid = low+(high-low)/2;
10          //大于等于的时候边界往前移
11          if (arr[mid]>=target)
12              high=mid-1;
13          //小于的时候边界mid处多移1步有可能将小值跳过去,因此调整到mid处
14          else if (arr[mid]<target)
15              low=mid;
16          //判断high是否已经小于目标值
17          if (arr[high]<target)
18          {
19              return arr[high];
20          }
21      }
22
23      return -1;
24  }

 2) 第1个大于某数的值

 1  int FindFirstBiggerNum(int arr[],int len,int target)
 2  {
 3      if (arr==NULL||len<=0)
 4          throw std::exception("Invalid input.");
 5
 6      int low=0,high=len-1;
 7      while(low<high)
 8      {
 9          int mid = low+(high-low)/2;
10          //大于等于的时候边界往前移
11          if (arr[mid]>target)
12              high=mid;
13          //小于的时候边界mid处多移1步有可能将小值跳过去,因此调整到mid处
14          else if (arr[mid]<=target)
15              low=mid+1;
16          //判断high是否已经小于目标值
17          if (arr[low]>target)
18          {
19              return arr[low];
20          }
21      }
22
23      return -1;
24  }

3. 二分查找之旋转数组的最小数字

  把一个数组最开始的若干个元素搬到数组的末尾, 我们称之数组的旋转。输入一个递增排序的数组的一个旋转, 输出旋转数组的最小元素。例如数组{3,4, 5, 1, 2 }为{ 1,2,3, 4,5}的一个旋转,该数组的最小值为 1。

仔细观察会发现旋转数组的最小值左边的数都大于最后一个数,右边的数都小于等于最后一个数,那么在二分查找的过程中与最后一个数比较来调整查找区间即可

 1  int FindMinNum(int arr[],int len)
 2  {
 3      if (arr==NULL||len<=0)
 4          throw std::exception("Invalid input.");
 5
 6      int lo=0,hi=len-1;
 7      int mid=0;
 8      while (lo<hi)
 9      {
10          mid=lo+(hi-lo)/2;
11          if (arr[mid]>arr[hi])
12          {
13              lo=mid+1;
14          }else if (arr[mid]<=arr[hi])
15          {
16              hi=mid;
17          }
18      }
19      return arr[lo];
20  }

  关于二分查找,http://www.cnblogs.com/ider/archive/2012/04/01/binary_search.html 这篇博客也有很好的总结。

引述该博客:

二分查找法的缺陷

  二分查找法的O(log n)让它成为十分高效的算法。不过它的缺陷却也是那么明显的。就在它的限定之上:有序。

  我们很难保证我们的数组都是有序的。当然可以在构建数组的时候进行排序,可是又落到了第二个瓶颈上:它必须是数组

  数组读取效率是O(1),可是它的插入和删除某个元素的效率却是O(n)。因而导致构建有序数组变成低效的事情。

  解决这些缺陷问题更好的方法应该是使用二叉查找树了,最好自然是自平衡二叉查找树了,自能高效的(O(n log n))构建有序元素集合,又能如同二分查找法一样快速(O(log n))的搜寻目标数。

时间: 2024-10-27 13:02:15

算法题16 二分查找及相关题目的相关文章

二分查找的相关算法题

最近笔试经常遇到二分查找的相关算法题 1)旋转数组中的最小数字 2)在旋转数组中查找某个数 2)排序数组中某个数的出现次数 下面我来一一总结 1 旋转数组的最小数字 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 实现数组的旋转见左旋转字符串. 和二分查找法一样,用两个指针分别指向数组的第一个元素和最后一个元素. 我们注意到旋转

Python 迭代器&amp;生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发

本节大纲 迭代器&生成器 装饰器  基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实的计算器所得出的结果一致 迭代器&

【算法拾遗】二分查找递归非递归实现

转载请注明出处:http://blog.csdn.net/ns_code/article/details/33747953 本篇博文没太多要说的,二分查找很简单,也是常见常考的查找算法,以下是递归非递归的实现. 非递归实现: /* 非递归实现,返回对应的序号 */ int BinarySearch(int *arr,int len,int key) { if(arr==NULL || len<1) return -1; int low = 0; int high = len-1; while(l

算法——基础篇——二分查找

     二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.     首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表.重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功

算法:时间复杂度+二分查找法(Java/Go/Python)实现

导读 曾几何时学好数据结构与算法是我们从事计算机相关工作的基本前提,然而现在很多程序员从事的工作都是在用高级程序设计语言(如Java)开发业务代码,久而久之,对于数据结构和算法就变得有些陌生了,由于长年累月的码砖的缘故,导致我们都快没有这方面的意识了,虽然这种论断对于一些平时特别注重学习和思考的人来说不太适用,但的确是有这样的一个现象. 而在要出去面试找工作的时候,才发现这些基础都快忘光光了,所以可能就"杯具"了!实际上,对于数据结构和算法相关的知识点的学习,是程序员必须修炼的一门内功

算法前戏 递归 二分查找 列表查找

一.递归 概念: 函数直接或者间接的调用自身算法的过程,则该函数称为递归函数.在计算机编写程序中,递归算法对解决一大类问题是十分有效的. 特点: ①递归就是在过程或者函数里调用自身. ②在使用递归策略时,必须有一个明显的结束条件,称为递归出口.问题规模相比上次递归有所减少, ③递归算法解题通常显得很简洁,但递归算法解题的效率较低.所以一般不倡导使用递归算法设计程序. ④在递归调用的过程当中系统的每一层的返回点.局部变量等开辟了栈来存储.递归函数次数过多容易造成栈溢出等. 所以一般不倡导用递归算法

【C/C++学院】0723-32位与64位/调戏窗口程序/数据分离算法/内存检索/二分查找法/myVC

[送给在路上的程序员] 对于一个开发者而言,能够胜任系统中任意一个模块的开发是其核心价值的体现. 对于一个架构师而言,掌握各种语言的优势并阿赫利运用到系统中,由此简化系统的开发,是其架构生涯的第一步. 对于一个开发团队而言,能在短期内开发出用户满意的软件系统是起核心竞争力的体现. 每一个程序员都不能固步自封,要多接触新的行业,新的技术领域,突破自我. 32位与64位 地址与内存的关系 4G = 4*1024M = 4*1024*1024k = 4*1024*1024*1024 Byte字节 =

算法图解(二分查找)

前言: 今天是第一篇 以后尽量每天写 看具体时间安排吧 目前一边学Python.Java.Go还有算法 所以写的比较少 主要是Python一天差不多16小时吧 Java.go看时间安排 这次算法全是用Python演示的 不懂Python的也没关系 或者可以看一下我前面的帖子 算法是什么: 算法是一只组完成任务的指令  要么速度快.要么能解决问题 应该说是为实现某些目的的逻辑 以及 思想 的代码 二分查找 假设你要查找电话本里k开头的人 里可能会直接滑动到中间 因为你知道k在中间位置 因为电话本是

Leetcode题解——算法思想之二分查找

1. 求开方 2. 大于给定元素的最小元素 3. 有序数组的 Single Element 4. 第一个错误的版本 5. 旋转数组的最小数字 6. 查找区间 正常实现 Input : [1,2,3,4,5] key : 3 return the index : 2 public int binarySearch(int[] nums, int key) { int l = 0, h = nums.length - 1; while (l <= h) { int m = l + (h - l) /