题目描述

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

示例 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
力扣原题目地址:https://leetcode.cn/problems/...

解法一,使用数组原生方法indexOf

var search = function (nums, target) {
    return nums.indexOf(target)
};

数组的原生方法,使用真方便。不过有时候需要多拓展一些处理问题的方式,以后遇到需求时,大有裨益

解法二,循环所有判断是否等于目标值

var search = function (nums, target) {
    let whichIndex = -1
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] == target) {
            whichIndex = i
            return whichIndex
        }
    }
    return whichIndex
};

假设我们要找的值,就是正好在最后一个位置,那么就得把整个循环全部走一遍,才能找到我们所要找的那个数值。所以时间复杂度就是O(n)。为了进一步提升效率,减少用时,所以二分法解题的方式就应运而生

解法三,二分法解题

所谓二分法可以简单理解为:

  • 指定开始位置、结束位置、然后不断缩小其范围最终找到我们想要找到的值;
  • 由于二分法的一半一半的缩小范围,所以其时间复杂度是O(\log n)

另外注意:

  • 二分法适用于有序的数组,即从小到大或者从大到小的数组
  • 二分法搭配while循环可读性会更加直观明了

在工作中for循环使用次数比较多,while循环并不是特别多,所以为了更好的理解二分法的,我们来简单复习一下while的循环知识

while循环复习

// 当符合condition条件的时候,会继续不断循环执行花括号里面的代码
// 所以当达到某种情况下的时候,需要让condition条件变为false,这样的话,才会结束循环
// 要不然就会死循环哦
while (condition) {
     // .....       
}

// eg:使用while循环打印0~10
let num = 0
while (num <= 10) { // 翻译:当num的值小于等于10的时候,就不断循环
    console.log(num);
    num++
}

while和for循环的区别

  • 固定数组、固定长度、固定执行次数一般使用for循环
  • 做边界区分、不知道要循环多少次一般使用while循环
  • while比for功能更加强大

二分法代码

var search = function (arr, num) {
    let firstIndex = 0
    let lastIndex = arr.length - 1
    // 注意firstIndex是要小于等于lastIndex值的,因为区间不断缩小最终重合
    while (firstIndex <= lastIndex) { 
        // console.log('firstIndex', firstIndex, 'lastIndex', lastIndex); // 看打印结果,有助于更好理解
        let middleIndex = Math.floor((firstIndex + lastIndex) / 2) // 数组长度为偶数时要向下取整,所以干脆都向下取整呗
        if (arr[middleIndex] == num) { // 若恰好中间索引数正好是我们所要找的那个数,返回索引即可
            return middleIndex
        } else if (arr[middleIndex] > num) { // 若中间数比要找的数大,说明要找到数在左边,那么开始区间不用动,结束区间更改为中间数左边一个位置即可
            lastIndex = middleIndex - 1
        } else if (arr[middleIndex] < num) { // 同理...
            firstIndex = middleIndex + 1
        }
    }
    return -1 // 找不到的话,返回-1
};

这里大家可以把while (firstIndex <= lastIndex) {......}改为while (true) {......}看看打印结果就会更好的理解了。虽然会死循环


水冗水孚
1.1k 声望585 粉丝

每一个不曾起舞的日子,都是对生命的辜负