35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
关键前提:排序数组、数组中无重复元素 ——> 二分法查找元素/边界
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
// 时间复杂度:O(log n)
// 空间复杂度:O(1)
var searchInsert = function (nums, target) {
let left = 0, right = nums.length; // 左闭右开
while (left < right) { // <
let mid = left + ((right - left) >> 1); // 右移运算符(>>)操作数每右移一位,相当于该数除以2向下取整(二进制)
if (nums[mid] === target) {
return mid; // 找到返回索引
}
else if (nums[mid] < target) {
left = mid + 1; // [mid+1, right)
}
else if (nums[mid] > target) {
right = mid; // [left, mid)
}
}
return right; // 未找到返回右边界
};
34. 在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
关键前提:排序数组 ——> 二分法查找左右边界
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
// 时间复杂度:O(log n)
// 空间复杂度:O(1)
// 二分法查找元素的左右边界
// 左闭右闭 <=
var searchRange = function (nums, target) {
return [searchLeftBorder(nums, target), searchRightBorder(nums, target)];
};
function searchLeftBorder(nums, target) {
let left = 0, right = nums.length - 1;
while (left <= right) {
let mid = left + ((right - left) >> 1);
if (nums[mid] < target) { // 查找左边界,小于target时更新左边界
left = mid + 1; // [mid+1, right]
}
else right = mid - 1;
}
if (left > nums.length - 1 || nums[left] != target) return -1; // 防止左边界越界,确保存在目标值
return left;
}
function searchRightBorder(nums, target) {
let left = 0, right = nums.length - 1;
while (left <= right) {
let mid = left + ((right - left) >> 1);
if (nums[mid] > target) { // 查找右边界,大于target时更新右边界
right = mid - 1; // [left, mid-1]
}
else left = mid + 1;
}
if (right < 0 || nums[right] != target) return -1; // 防止右边界越界,确保存在目标值
return right;
}
69. X的平方根
给你一个非负整数 x
,计算并返回 x
的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5)
或者 x ** 0.5
。
视为0到X的数组 ——> 二分法查找元素/左边界
/**
* @param {number} x
* @return {number}
*/
// 算术平方根 二分查找解法
var mySqrt = function (x) {
let left = 0, right = x; // 左闭右闭
while (left <= right) { // <=
let mid = left + ((right - left) >> 1);
if (mid * mid === x) return mid; // 等于 找到目标值
else if (mid * mid > x) right = mid - 1; // 大于 缩小右边界[left, mid-1]
else if (mid * mid < x) left = mid + 1; // 小于 扩大左边界[mid+1, right]
}
return left - 1; // 结果只保留整数部分,向下取整
};
367. 有效的完全平方数
给你一个正整数 num
。如果 num
是一个完全平方数,则返回 true
,否则返回 false
。
完全平方数 是一个可以写成某个整数的平方的整数。换句话说,它可以写成某个整数和自身的乘积。
不能使用任何内置的库函数,如 sqrt
。
视为0到num的数组 ——> 二分法查找元素
/**
* @param {number} num
* @return {boolean}
*/
// 有效的完全平方数 二分查找法
// 能找到目标值(整数)return true,否则return false
var isPerfectSquare = function (num) {
let left = 0, right = num; // 左闭右闭
while (left <= right) { // <=
let mid = left + ((right - left) >> 1); // 位运算,右移一位,相当于除以2
if (mid * mid === num) return true;
else if (mid * mid > num) right = mid - 1;
else if (mid * mid < num) left = mid + 1;
}
return false;
};