携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情。
704 二分查找
直达:704 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
快速解法
/**
* @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 mid = Math.floor((right - left) / 2) + left;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
return mid;
}
}
return -1;
};
思路:
已知数组为有序数组,所以可以使用二分查找法来查找目标。
二分查找法是比较基础的算法,可以定义 left 和 right 来表示查找范围,在条件允许的情况下(left <= right),不断定义中点 mid,并通过中点的值和目标值进行比较不断确认查找范围,知道找到目标。
复杂度分析:
- 时间复杂度:
O(log n)。n是数组的长度,log n是二分查找消耗的时间。 - 空间复杂度:
O(1)。
278 第一个错误的版本
直达:278 第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
快速解法
/**
* Definition for isBadVersion()
*
* @param {integer} version number
* @return {boolean} whether the version is bad
* isBadVersion = function(version) {
* ...
* };
*/
/**
* @param {function} isBadVersion()
* @return {function}
*/
var solution = function(isBadVersion) {
/**
* @param {integer} n Total versions
* @return {integer} The first bad version
*/
return function(n) {
let left = 1;
let right = n;
while (left < right) {
const mid = Math.floor((right - left) / 2) + left;
if (isBadVersion(mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
};
};
思路:
这道题主要在于一开始可能没法理解,其实就是通过调用参数传入的函数 isBadVersion 来判断是否是错误版本,isBadVersion(mid) = true 表示是错误版本。
然后和上一题一样,使用二分查找来解决,略有不同的是,查找条件是 left < right,是实操中:
- 每次判断是错误版本,会设置
right = mid,保证right是错误版本 - 每次判断是正确版本,会设置
left = mid + 1,而mid始终是正确版本,left却有可能是错误版本 - 当
left是错误版本时,要么进入新的循环,但是mid始终是错误版本,所以right的值会逐渐接近left的值,即left === right,就是第一次错误版本 - 当
left是错误版本时,要么不进入新的循环,即left === right,就是第一次错误版本
复杂度分析:
- 时间复杂度:
O(log n)。n是数组的长度,log n是二分查找消耗的时间。 - 空间复杂度:
O(1)。