这是leetcode面试刷题一题多解系列的第三篇,今天给大家来一个简单点的,练习下在数组有序的情况下最常用的提升性能的查找方法,二分查找。
题目
今天跟大家一起看一道经典的二分查找的算法题,搜索插入位置。
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
来源:力扣(LeetCode)
链接:leetcode.cn/problems/se…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解1---顺序查找
这是这道题最简单也是最直接的一种思路,既然数组有序,那么就顺序去查找,最差情况遍历一遍数组的所有数据项。时间复杂度是 O(N),空间复杂度 O(1)。
var searchInsert = function (nums, target) {
for (let i = 0; i < nums.length; i++) {
if (nums[i] >= target) {
return i;
}
}
return nums.length;
};
题解3--二分法查找
二分法的基本思想是将待查找区间一分为二,然后判断待查找元素在哪个子区间中,再将该子区间作为新的待查找区间,重复以上步骤,直到找到该元素或确定该元素不存在为止。由于每次查找都将待查找区间缩小一半,因此这种算法的时间复杂度为O(logN),比线性查找的O(N)要快很多,空间复杂度O(1)。
var searchInsert = function(nums, target) {
const n = nums.length;
// left和right分别为区间的左右边界,ans的初始值为n(即整个数组的最后)
let left = 0, right = n - 1, ans = n;
// 循环条件,保证所有数据项都被考虑
while (left <= right) {
// 求得区间中间位置索引
let mid = ((right - left) >> 1) + left;
// 在左半区间
if (target <= nums[mid]) {
ans = mid;
right = mid - 1;
} else {
// 右半区间
left = mid + 1;
}
}
return ans;
};
初始化变量n为数组nums的长度,left为0,right为n-1,ans为n。其中ans表示插入元素在nums中的位置,如果target已经存在于nums中,则ans为其在nums中的下标;如果target不存在于nums中,则ans为插入target后nums仍然保持有序的位置,其中mid = ((right - left) >> 1) + left ,表示待查找区间的中间位置,计算mid的常见方式是将待查找区间的左右边界相加再除以2。但是,这种计算方式可能会在边界比较大的情况下出现整型溢出的问题,所以采用了相减的方式,>> 是位运算符,相当于除以2的指数次方。