常用算法整理:二分查找
来源:互联网 发布:java.util.date怎么用 编辑:程序博客网 时间:2024/05/17 22:29
基础二分查找
二分查找是大家最常用的也是最简单的一种算法。二分查找在面试中是非常常见的一题,而且很多时候二分查找是时间效率最高的一种搜索方式。
最简单的二分查找就是查找有序不重复数组中给定值的位置,基本模板如下:
var search = function(nums, target) { var s = 0, e = nums.length - 1, m; while(s+1<e) { m = parseInt((s+e)/2); if(nums[m] === target) { return m; } else if(nums[m] < target) { s = m; } else { e = m; } } if(nums[s] === target) return s; if(nums[e] === target) return e; return -1;};
这里一个技巧就是,为了防止不小心陷入无限循环,当两个指针相邻的时候即结束循环,然后需要判断下头指针和尾指针的值是否满足条件。
这个必须掌握,要写出bug free的代码,但是这个太简单了,所以实际出题的时候肯定不会直接出这么简单题目。
进阶二分查找
进阶二分查找题目依然是在有序数组中找到一个给定值,不过会出现一些变化,这里说几个经典的题目。
第一种是搜索有重复的数组中第一个出现的或者最后一个出现的目标值的位置。
这里直接给一个综合的就是 Search for a range
,在有重复的排序数组中找到指定值出现的范围,就要同时找到第一个出现的值和最后一个出现的值。
题目链接:https://leetcode.com/problems/search-for-a-range/
为了方便,这里我分成找第开头和找结束两步来进行:
var searchRange = function(nums, target) { var result = [-1,-1]; //找开头 var s = 0, e = nums.length-1, m; while(s+1<e) { m = Math.floor((s+e)/2); if(nums[m] >= target) { e = m; } else { s = m; } } if(nums[s] === target) result[0] = s; else if(nums[e] === target) result[0] = e; else return result; //找开头 s = 0, e = nums.length-1, m; while(s+1<e) { m = Math.floor((s+e)/2); if(nums[m] <= target) { s = m; } else { e = m; } } if(nums[e] === target) result[1] = e; else if(nums[s] === target) result[1] = s; return result;};
第二种,比较简单,叫 first bad version
,就是说在 1~n
个版本中有一个版本是错误的,然后给出了一个函数可以检测指定的版本是否有错误。
题目链接 https://leetcode.com/problems/first-bad-version/
这种题目就是二分查找的方式几乎没有难度,但是会有稍微一点变化,比如这一题就是认识到通过 isBadVersion
函数来判断保留左边还是右边。
解法如下:
var solution = function(isBadVersion) { return function(n) { var s = 1, e = n, m; while(s+1<e) { m = Math.floor((s+e)/2); if(isBadVersion(m)) { e = m; } else { s = m; } } if(isBadVersion(s)) return s; if(isBadVersion(e)) return e; };};
最后一个最难的个叫 Search in rotated sorted array
,就是数组从某一个位置被翻转了一下,比如 [0,1,2,3,4,5]
被翻转成了 [3,4,5,0,1,2]
当然题目是不会告诉我们从哪里翻转的。那么我们有两个解法,一种是先通过二分查找找到翻转点,然后分别对左右两个有序数组进行二分查找,另外一个就是只用一次二分查找就可以解决,但是要注意移动指针的方式。
var search = function(nums, target) { var s = 0, e = nums.length-1, m; while(s+1<e) { m = parseInt((s+e)/2); if(nums[m] === target) return m; else if(nums[m] < nums[s]) { if(nums[m] <= target && target <= nums[e]) { s = m; } else { e = m; } } else { if(nums[m] >= target && target >= nums[s]) { e = m; } else { s = m; } } } if(nums[s] === target) return s; if(nums[e] === target) return e; return -1;};
解法如上, 这一题的要点就是确定指针应该如何移动,这里我们会通过比较 nums[s],nums[m],nums[e],target
四个变量来确定如何移动指针,过程有点复杂但是基本原理就是确定target到底是在m的左边还是右边。
还有类似的比这个简单一些,只要找最小值 https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/
另外还有 sqrt
,find peak
等题目。
- 常用算法整理:二分查找
- 常用算法整理:二分查找
- 二分查找算法整理
- 常用算法- 二分查找
- 常用算法之二分查找
- 算法整理-二分查找列表最大值
- 【算法】常用的查找算法之二分查找法
- 查找算法 二分查找
- 查找算法:二分查找
- 算法--查找--二分查找
- 查找算法---二分查找
- 二分查找整理
- 常用算法回顾——二分查找算法
- [算法]二分查找算法
- 算法----二分查找算法
- 查找算法:二分查找算法
- 常用算法——二分查找(Binary Search)
- 常用二分查找模板
- 欧拉函数の应用;;;
- Ural1079-Maximum
- Yii 快速入门-初级教程
- 不定方程
- 两个文件的回调简单记录一下
- 常用算法整理:二分查找
- MongoDB 3.2.7 for rhel6.4 副本集-分片集群部署
- Linux下源码编译安装node.js
- spring注解
- mybatis 利用mysql盲注
- NOIP11.15模拟 T2 三部曲
- Node.js 中文乱码解决---响应中文乱码
- iOS10.0自带的刷新控件UIRefreshControl简介
- 奥巴马精彩演讲:我们为什么要上学