一. 先用js实现二分法 , 用二分法查找有序数组中的目标target
- 数组: [1,2,3,4,5,6,7,8,9,10]
- target : 9
使用二分法查找数组中的 9 ,返回找到的下标 , 没有则返回-1
计算的时候有个小坑 ,js使用 /
的时候是会保留小数的 , 所以要用Math.floor取整
或者使用位运算>>1
没什么好讲的 , 这个模板就算你不会都要背下来
var search = function(nums,target){
let left = 0
let right = nums.length
while(left<=right){//[left,right]所以当left等于right时是有意义的
//每次循环都重新计算mid
const mid = Math.floor((right-left)/2) + left
const num = nums[mid]
if(target > num){
left = mid + 1
}else if(target < num){
right = mid - 1
}else
return mid
}
return -1
}
const result = search(nums,target)
console.log(result);
二 . 判断什么题目使用二分法
下面给出几个使用二分法的题目 , 让我们来解析一下什么样的题目适合使用二分法
数组: [1,2,3,4,5,6,7,8,10,10] ____ target : 9
- 查找有序数组中与
target相等
的目标元素 , 没有则返回-1
(返回-1) - 查找有序数组的与
target相等
的目标元素 , 没有则返回target 插入有序数组的下标
(返回8) x的平方根
- 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。不可以使用内置函数,由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
有效的完全平方数
- 给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。
第一题就是上面的题目 , 让我们从第二题开始
2. 查找有序数组的与target相等
的目标元素 , 没有则返回 target 插入有序数组的下标
这道题有两种情况 , 找到target , 找不到target
解决方法 : 只在当前 mid值 大于等于
target 的时候保存当前的mid , 因为每次保存的 mid 值都是大于target值的 , 直到找到target或者while结束 找不到target
, 而此刻的mid 正是我们要插入的target的位置
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
let left = 0
let right = nums.length-1
//要返回的大于target的最小下标
let index = nums.length
while(left<=right){
//每次都找一下中间
let mid = Math.floor((right-left)/2)+left
if(nums[mid]>=target){
right = mid-1
index = mid
}
else{
left = mid+1
}
}
//找不到就返回大于target的最小下标
return index
};
3. x的算术平方根
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。不可以使用内置函数,由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
这个数组中的元素可以被分为两部分 , 平方之后小于等于x的 , 平方之后大于x
解决方法: 首先我们定义一个区间 , left = 0 , right = 1000000 , 用while循环 , 找到平方之后小于x的最大的那个值 , 一直缩小查找范围
, 直到找到平方之后等于x的
或者平方之后小于x的最大值
/**
* @param {number} x
* @return {number}
*/
var mySqrt = function(x) {
let l = 0
let r = 10000000
let ans = 0
while(l<=r){
let mid = (l+r)>>1
if(mid*mid<=x){
ans = mid
l = mid +1
}
else{
r = mid -1
}
}
return ans
};
4. 给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。
设定一个[0,1000000]的区间 , 里面的值可以被分为两种情况 , 一种是平方之后等于num的 , 一种是平方之后不等于num的 , 所以我们就可以使用二分法来缩小区间 , 得到精确的结果
/**
* @param {number} num
* @return {boolean}
*/
var isPerfectSquare = function(num) {
let l = 0
let r = 1000000
let ans = 0
while(l<=r){
let mid = (l+r)>>1
if(mid*mid<=num){
ans = mid
l = mid+1
}else
r = mid-1
}
return ans*ans==num
};