【算法-LeetCode】704. 二分查找

704. 二分查找 - 力扣(LeetCode)

发布:2021年8月5日12:12:25

问题描述及示例

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的题解

主要思路是用两个指针leftright分别指向待查找的数组(或者说是子数组)的最左端和最右端,然后用mid指针始终指向两端的中点位置(leftrightmid存储的都是相应的数组下标)。由于题目说了原数组是有序且是升序的,那么就可以将targetmid指针所指向的nums[mid]作比较。如果targetnums[mid]大的话,则说明target一定不在nums[left] ~ nums[mid]这个范围内,此时将left指针更新指向至nums[mid+1]处;反之,如果targetnums[mid]小的话,则说明target一定不在nums[mid] ~ nums[right]这个范围内,此时将right指针更新指向至nums[mid-1]处。重复这个过程,直到找到与target相等的数组元素,并返回其下标;若数组中不存在该元素,则返回-1

本来想做个动图演示的,但是前几次的经验告诉我,这太麻烦了,而且这个思路用上面的文字讲述应该已经挺明白了,以后回顾的时候应该能看懂,那就先不做图了。

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function(nums, target) {
  // 原始数组nums就是一开始的待查找数组,所以将left初始化为0,right初始化为length-1
  let left = 0;
  let right = nums.length - 1;
  let mid; 
  // 如果left指针还在right指针左边,说明target还有可能在left到right之间被找到
  // 要是left和right指向同一个元素,说明要么这个元素就是target,要么就是数组里没有target
  while(left <= right) {
    // mid = Math.floor(left/2 + right/2);
    // 这里为什么要用Math.floor和(right - left) / 2 + left,请看下方详解
    mid = Math.floor((right - left) / 2 + left);
    // 如果刚好命中target,则将target下标返回,注意题目里说可以认为数组里没有重复元素
    if(nums[mid] === target) {
      return mid;
    }
    // 如果target在nums[mid]右边,则移动left指针到mid+1
    if(nums[mid] < target) {
      left = mid + 1;
    } else {
    // 如果target在nums[mid]左边,则移动right指针到mid-1
      right = mid - 1;
    }
  }
  // 一旦left指针出现在right指针右边,说明target压根就不在数组里
  return -1;
};


提交记录
39 / 39 个通过测试用例
状态:通过
执行用时:64 ms, 在所有 JavaScript 提交中击败了97.87%的用户
内存消耗:41.3 MB, 在所有 JavaScript 提交中击败了40.30%的用户
时间:2021/08/05 11:20

为什么要用Math.floor(right - left) / 2 + left

  • 首先是Math.floor:下面是我自己做的验证,由下图可知,如果数组下标为非整数,那么可能会出现无法取值的情况。而mid计算出的结果有可能不是整数,所以用Math.floor确保数组的下标取整,当然,理论上用Math.ceil也可以。

在这里插入图片描述

  • 其次是(right - left) / 2 + left:这个式子化简出来其实就是(right+left) / 2,按理来说,直接用化简出来的式子不是更直观吗?这是为了防止整数溢出,因为nums数组可能非常长,那么此时right + left的值就可能非常大,从而超出整数表示范围而导致异常。

有关二分查找,其实我一直有个疑问,那就是为什么非得用两个端点的中间值作为分割点呢?其实一开始我也觉得用中间点是理所当然的,后来不知道从哪里听别人提过这个问题,于是心里也有了相关的疑惑,我开始的想法是:可能这样才能达到最好的平均查找性能吧。今天我特意搜了一下,发现网上有关的讨论不多,看到有个网友说得似乎挺有道理的,详细看下方参考链接。

参考:为什么二分查找要取中点作为每次的划分点_Rachelint的博客-CSDN博客

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

更新:2021年8月5日12:17:01

参考:二分查找 - 二分查找 - 力扣(LeetCode)

【更新结束】

有关参考

更新:2021年8月5日12:27:56
参考:五种js判断是否为整数(转) - 云端观云 - 博客园
参考:javascript数组中数字和非数字下标的区别_不吃鱼的猫-CSDN博客_数组下标可以不是数字吗

更新:2021年8月5日12:50:16
参考:为什么二分查找要取中点作为每次的划分点_Rachelint的博客-CSDN博客
参考:二分查找各种情况大总结_yefengzhichen的博客-CSDN博客
参考:二分查找专题(二)_K_天道酬勤-CSDN博客

更新:2021年8月5日13:31:25
参考:二分查找法的细节(mid值 整数溢出问题)_eddie’s Blog-CSDN博客_二分查找 溢出

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值