在数组上查找元素 二分查找 降低时间复杂度
哈喽哈喽,我是你们的金樽清酒,算法的功底对于一个程序员来说是很重要,我的算法水平又很烂,所以我询问学长如何去学习算法,学长跟我说可以跟着代码随想录一步步来,然后我就开始了代码随想录的第一章,学习数组。如何用二分查找降低时间复杂度。
二分查找的应用场景
在一个有序且无重复的数组上,如果你想找到某一个元素的话,就可以用二分查找的方法。 我们正常的解法是遍历数组,找到数组有没有该元素。可是当数组特别庞大的时候,要遍历的元素还是蛮多的,这个时候我们就可以用二分查找来降低时间复杂度。
什么是二分查找
二分查找(Binary Search)是一种在有序数组或列表中查找特定元素的算法。它的基本思想是将目标元素与数组或列表的中间元素进行比较,如果目标元素等于中间元素,则查找成功;如果目标元素小于中间元素,则在数组的前半部分继续查找;如果目标元素大于中间元素,则在数组的后半部分继续查找。通过不断地缩小查找范围,最终可以找到目标元素或确定目标元素不存在。
这样的话,我们就需要定义三个变量,左指针,右指针和一个中间值。判断元素与中间下标元素的大小关系。如果小于就往左边找,如果大于就往右边找,不断的缩小范围,直到左指针大于右指针(出口条件)没有找到返回-1,期间找了返回下标。
实战
js
let nums = [-1, 0, 3, 5, 9, 12]//找到目标值为9的下标
var search = function (nums, target) {
let mid, left = 0
let right = nums.length - 1
while (left <= right) {
mid = left + ((right - left) >> 1)
if (target > nums[mid]) {
left = mid + 1
} else
if (target < nums[mid]) {
right = mid - 1
}
else {
return mid
}
}
return -1
};
console.log(search(nums,9))
lootcode题目
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
示例 1:
makefile
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
makefile
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
提示:
- 你可以假设
nums
中的所有元素是不重复的。 n
将在[1, 10000]
之间。nums
的每个元素都将在[-9999, 9999]
之间。
这道题就可以直接用二分查找,二分查找可以符合这个时间复杂度。
js
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var search = function(nums, target) {
//手写一个二分查找
let mid,left=0
let right=nums.length-1
while(left<=right){
mid=left+((right-left)>>1)
if(target>nums[mid]){
left=mid+1
}else
if(target<nums[mid]){
right=mid-1
}else{
return mid
}
}
return -1
};
注意边界问题
如果你的右指针定义为数组的长度,那就是左闭右开,那while的条件就是left<right,等号不能存在,不在数组范围,但是如果右指针你为定义的是数组长度-1的话while里面的条件就是left<=right,最右边也在数组的范围内,所以有两种写法一一对应,可千万不要写反哦。
- 两种边界情况的写法
js
//左闭右闭
var search = function (nums, target) {
let mid, left = 0
let right = nums.length - 1
while (left <= right) {
mid = left + ((right - left) >> 1)
if (target > nums[mid]) {
left = mid + 1
} else
if (target < nums[mid]) {
right = mid - 1
}
else {
return mid
}
}
return -1
};
js
//左闭右开的情况
var search = function (nums, target) {
let mid, left = 0
let right = nums.length
while (left <=right) {
mid = left + ((right - left) >> 1)
if (target > nums[mid]) {
left = mid + 1
} else
if (target < nums[mid]) {
right = mid - 1
}
else {
return mid
}
}
return -1
};