算法刷题——二分法

·  阅读 1518

704 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
复制代码

链接:leetcode-cn.com/problems/bi…

解题思路

暴力解决的话就是从头开始遍历数组,但由于这个数组是有序的,所以可以优化成二分查找。即从中间开始查找,根据结果的大小再向左或者向右查找。

二分查找的基本框架:设置一个left指针,一个right指针,mid = floor((left+right)/2),循环条件是left<=right,查看Mid是否是要查找的数,不是的话根据大小移动左右指针缩小范围继续查找。、

时间复杂度是O(logn)

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function(nums, target) {
    let right = nums.length - 1;
    let left = 0;
    while(left <= right){
        let mid = Math.floor((right + left) / 2);
        if(nums[mid] === target)
            return mid;
        if(nums[mid] > target){
            right = mid - 1;
        }else{
            left = mid + 1 ;
        }
    }
    return -1;
};
复制代码

69 x的平方根

实现 int sqrt(int x) 函数。计算并返回 x 的平方根,其中 x 是非负整数。由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
复制代码

解题思路

这个题暴力解决的话就是枚举从1到x的数所有数,比较其平方是否和x一样。同上因为有序所以可以优化为二分查找。

这道题的容易忽略的点是如果不是恰好相等,我们要返回比sqrt(x)小的最大的那个整数,所以如果遇到mid * mid < x,就要更新res,这时候肯定是向右寻找的,如果继续寻找依然符合这个条件,那么就会增大res,,从而在结束循环的时候得到res。

/**
 * @param {number} x
 * @return {number}
 */
var mySqrt = function(x) {
    if(x === 0)
        return 0;
    if(x === 1)
        return 1;
    let left = 0;
    let right = x;
    let res = -1;
    while(left <= right){
        let mid = Math.floor((left + right) / 2);
        //let mid = (left + right) >> 1; 也可以用移位
        let sum = mid * mid;
        if(sum === x)
            return mid;
        if(sum > x){
            right = mid - 1;
        }else{
            res = mid;
            left = mid + 1;
        }
    }
    return res;
    
};
复制代码

50Pow(x, n)

实现 pow(x, n) ,即计算 x 的 n 次幂函数。

示例 1:
输入:x = 2.00000, n = 10
输出:1024.00000
示例 2:
输入:x = 2.10000, n = 3
输出:9.26100
示例 3:
输入:x = 2.00000, n = -2
输出:0.25000
解释:2-2 = 1/22 = 1/4 = 0.25
复制代码

链接:leetcode-cn.com/problems/po…

解题思路1

暴力计算,但是会超时

/**
 * @param {number} x
 * @param {number} n
 * @return {number}
 */
let myPow = function(x, n) {
    if(x === 0)
        return 0;
    if(n === 0)
        return 1;
    let sum = 1;
    let mi = n > 0 ? n : -n;
    while(mi--){
        sum *= x;
    }
    if(n > 0){
        return sum;
    }else{
        return 1 / sum;
    }
};
复制代码

解题思路2

快速幂方法 : 正数情况下,如果n为偶数x ^ n = (x * x) ^ (n / 2),如果n为奇数x ^ n = x * x ^ (n - 1)。

/**
 * @param {number} x
 * @param {number} n
 * @return {number}
 */
let myPow = function(x, n)  {
    if(n === 0)
        return 1;
    if(n === 1)
        return x;
    let abs = Math.abs(n);
    let isMinus = n !== abs;
    let sum = abs % 2 ? x * myPow(x,abs-1): myPow(x*x, abs/2);
    return isMinus ? 1 / sum : sum;

};
复制代码
分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改