Math.floor(left + (right - left) / 2)
704. 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
left=0 right=5 mid=2 nums[mid]=3
left=3 right=5 mid=4 nums[mid]=9
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var search = function(nums, target) {
let left = 0;
let right = nums.length - 1;
let res = -1;
while(left <= right) {
let mid = (right + left) >> 1;
console.info('left='+left+' right='+right);
console.info('mid='+mid+' nums[mid]='+nums[mid]);
if(nums[mid] === target) {
res = mid;
break;
}
if(nums[mid] > target) right = mid - 1;
if(nums[mid] < target) left = mid + 1;
}
return res;
};
875. 爱吃香蕉的珂珂
珂珂喜欢吃香蕉。这里有 N 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 H 小时后回来。
珂珂可以决定她吃香蕉的速度 K (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 K 根。如果这堆香蕉少于 K 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在 H 小时内吃掉所有香蕉的最小速度 K(K 为整数)。
输入: piles = [3,6,7,11], H = 8
输出: 4
/**
* @param {number[]} piles
* @param {number} h
* @return {number}
*/
var minEatingSpeed = function(piles, h) {
let left = 1;
let right = Math.max(...piles);
while (left <= right) {
const mid = Math.floor(left + (right - left) / 2);
if (canFinish(piles, mid, h)) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return left;
};
function canFinish (piles, speed, h) {
let time = 0;
for (let n of piles) {
time += (n / speed | 0) + ((n % speed > 0) ? 1 : 0);
}
return time <= h;
}
35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n)
的算法。
输入: nums = [1,3,5,6], target = 5
输出: 2
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
let left = 0;
let right = nums.length - 1;
let index = nums.length;
while(left <= right){
let mid = (left + right) >> 1;
if(target > nums[mid]) {
left = mid + 1;
} else {
index = mid;
right = mid - 1;
}
}
return index;
};
69. Sqrt(x)
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
输入: x = 8
输出: 2
解释: 8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
/**
* @param {number} x
* @return {number}
*/
var mySqrt = function(x) {
let [l,r] = [0,x];
let ans = -1;
while(l <= r){
const mid = (l+r) >> 1;
if(mid * mid > x){
r = mid - 1;
} else {
ans = mid;
l = mid + 1;
}
}
return ans;
};
278. 第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
输入:n = 5, bad = 4
输出:4
解释:
调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true
所以,4 是第一个错误的版本。
/**
* 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 = 0; let right = n - 1;
let res = n;
while (left <= right) {
const mid = Math.floor(left + (right - left) / 2);
if (isBadVersion(mid)) {
res = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return res;
};
};