javascript 之二分查找

简介: javascript 之二分查找

大家好,我是 17

写二分的时候,不要每次都重新写,而是记住一个模板,每次都用这个模板。这样做的好处是不容易出错,而且速度快,特别适合面试。

function binarySearch(nums, target) {
   let low=0,high=nums.length
   while(low<high){
       let mid=low+((high-low)>>1)
       if(nums[mid]>=target) high=mid
       else low=mid+1
   }
   return low
};
复制代码
输入 输出
[ 1,2,2,4 ] , 2 1
[ 1,2,2,4 ] , 4 4
[ 1,2,2,4 ] , 3 3
[ 1,2,2,4 ] , 0 0

把模板当作一个黑盒,熟记什么样的输入会有什么样的输出。

如果 nums 是升序

  1. 如果 target 存在,一定会找到,如果有相同值,命中最左边的位置
  2. 如果不存在,会命中 比 target 略大的值
  3. 如果 target 大于所有值,会超出最右边界 low == nums.length
  4. 如果 target 小于所胡值, low == 0

总的来说,就两条,如果 target 存在,命中最左置,如果不存在,命中偏右位置(如果 target 存在,相比于 target的位置)

(high-low)>>1  等价于 Math.floor((high-low)/2),如果你不习惯于移位的写法,也可以这么写。

要这么写low+ Math.floor((high-low)/2)而不是 Math.floor((high+low)/2) 是因为 high+low可能会溢出,超出 数字的最大表示范围。

[low,high) 左闭右开,也就是说,high的位置比可以取到的位置 加 1,一定要记住。

熟记上面的模板后,我们先练练手。

704 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

解题:这是最简单的二分查找题目,直接用模板即可。如果目标值存在,则一定能找到。

var search = function(nums, target) {
   let low=0,high=nums.length
   while(low<high){
       let mid=low+((high-low)>>1)
       if(nums[mid]>=target) high=mid
       else low=mid+1
   }
   return nums[low]===target?nums[low]:-1
};
复制代码

35. 搜索插入位置

给定一个按升序排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

解题:根据模板特性 第1条,目标值存在则一定找到,并可以返回索引。如果不存在,根据模板特性 第2条 ,返回 比 target 略大的值,正好是插入的位置。代码和模板一模一样。

var searchInsert = function(nums, target) {
   let low=0,high=nums.length
   while(low<high){
       let mid=low+((high-low)>>1)
       if(nums[mid]>=target) high=mid
       else low=mid+1
   }
   return low
};
复制代码

367. 有效的完全平方数

给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false

解题:可以认为是 从 大于等于1 到 小于等于 num 的数中,看看能不能选出一个数 x x * x = num 如果存在,根据 模板特性1 一定会找到,如果不存在 ,根据特性2 ,会命中一个稍大的数。根据左闭右开的原则,low = 1 ,1是可以取到的最小值,high=num+1 num是可以取到的最大值

var isPerfectSquare = function (num) {
  let low = 1, high = num + 1
  while (low < high) {
    let mid = low + ((high - low) >> 1)
    if (mid * mid >= num) high = mid
    else low = mid + 1
  }
  return low * low == num
};
复制代码

接下来,自己到 leetcode 上面找几道简单题练习一下,切记用模板,只能修改两个地方,其它地方都不要修改。

nums[mid]>=target 这个判断是可以修改的,这也查为什么二分查找不适合成一个通用方法的原因

return low 返回值这里 根据题意 灵活修改。

如果 nums里面有重复数,模板是命中最左边的位置 ,如果想要命中最右边的位置

nums[mid]>target
...
return low-1
复制代码

如果你都顺利通过了,说明你已经掌握了模板,可以尝试些复杂些的题目了。这些题目的关键在于如何找到二分的条件。

153. 寻找旋转排序数组中的最小值

题解:最小值一定在两段有序数组的交界偏右的位置。如果中值比nums[0]小,说明交界一定在左侧,否则在右侧。 根据 模板 特性1 如果 交界 存在,则一定找到 。如果交界不存在,也就是 数组整个有序,那么 nums[mid]<nums[0] 永远为假,high 最后的结果 就是 nums.length,low 的退出条件是 等于 high,low == nums.length

var findMin = function(nums) {
   let low=0,high=nums.length
   while(low<high){
       let mid=low+((high-low)>>1)
       if(nums[mid]<nums[0]) high=mid
       else low=mid+1
   }
   return nums[low]?? nums[0]
};
复制代码

34. 在排序数组中查找元素的第一个和最后一个位置

题解:用模板可以找到最左面的位置,最右边的位置可以用 前面讲到的

nums[mid]>target
...
return low-1
复制代码
var searchRange = function(nums, target) {
    let low=0,high=nums.length;
    let ans=[]
    while(low<high){
        let mid=low+((high-low)>>1)
        if(nums[mid]>=target) high=mid
        else low=mid+1
    }
    if(nums[low]!==target) return [-1,-1]
    ans[0]=low
    high=nums.length
    while(low<high){
         let mid=low+((high-low)>>1)
         if(nums[mid]>target) high=mid
        else low=mid+1
    }
    ans[1]=low-1
    return ans
};
复制代码

把上面提到的都熟记后,找几道题练练,二分的基本功就差不多了

目录
相关文章
|
6天前
|
算法 JavaScript 前端开发
JavaScript算法和数据结构:写一个二分查找的函数。
JavaScript算法和数据结构:写一个二分查找的函数。
33 0
|
JavaScript 前端开发 算法
【前端算法】javaScript实现二分查找
如何使用JS实现一个合格的二分查找
195 0
|
前端开发 算法 JavaScript
LeetCode二分查找使用JavaScript破解|前端学算法
LeetCode二分查找使用JavaScript破解|前端学算法
57 0
LeetCode二分查找使用JavaScript破解|前端学算法
|
2天前
|
存储 JavaScript 前端开发
从零开始学习Vue.js
Vue.js 是一种流行的前端框架,它使用简单,灵活且易于上手。如果你是一个前端开发者,并想要学习 Vue.js,本文将为您提供一个从零开始的指南。我们将探讨 Vue.js 的基础知识和常用功能,以及如何构建一个简单的 Vue.js 应用程序。
|
4天前
|
缓存 JavaScript 前端开发
JavaScript:get和post的区别,2024年最新3-6岁儿童学习与发展指南心得体会
JavaScript:get和post的区别,2024年最新3-6岁儿童学习与发展指南心得体会
|
5天前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
6天前
|
XML Web App开发 前端开发
字节FE:JavaScript学习路线图
字节FE:JavaScript学习路线图
10 0
|
6天前
|
存储 移动开发 JavaScript
学习javascript,前端知识精讲,助力你轻松掌握
学习javascript,前端知识精讲,助力你轻松掌握
|
6天前
|
JavaScript 前端开发 测试技术
学习JavaScript
【4月更文挑战第23天】学习JavaScript
15 1