难度:简单
题目:
给定一个 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
提示:
你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。
解题思路:
解决这道题的关键是在于理解二分查找
1、前提条件:
1、有序
2、只查找一个而不是多个
2、核心思想:(默认数组递增)
对于有序数组想要查询到目标,首先将数组中间值与目标比对,如果比配成功,皆大欢喜!如果不等,则可以排除掉一半的不符合数据,将此过程不断迭代,最终找到目标或是返回无目标,查询失败。
3、整体时间复杂度:
o(log n)
4、边界问题:
与target比较的中间数字是否要加入到下次查找中?
因此,二分查找中目标元素对应区间的定义十分重要:
- [left,right]
循环条件:while(left <= right)
判断 if(nums[middle] > target) right = middle -1
- [left,right)
循环条件:while(left < right)
判断 if(nums[middle] > target) right = middle
为什么会这样写呢,主要是因为如果这个时候left的值为middle - 1,target也为nums[middle - 1],如果在left<right这样的判断条件下,赋值right 为 middle - 1,那么就不会再进入while循环了,这个时候就找不出target所在的位置。
JavaScript 实现:
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var search = function(nums, target) {
let left = 0
let right = nums.length - 1
while (left <= right){
const middle = Math.floor((left + right) / 2)
if(nums[middle] === target){
return middle
}else if(nums[middle] < target){
left = middle + 1
}else if(nums[middle] > target){
right = middle - 1
}
}
return -1
};