数据结构与算法-学习笔记(11)

二分查找

思路:根据中间点确定目标值范围,然后不断缩小范围直到找到。

时间复杂度

假设查找k次,当k值增大,n/2……k = 1时,k=log2n,因此时间复杂度O(k) = O(logn)。

而logn这种对数时间复杂度,是一种极其高效的时间复杂度,即使n非常大,对应的logn也很小。例如:当n=42亿时,logn=32。并且有时常量级时间复杂度O(1)的执行效率都不如对数的时间复杂度。

代码(有序数组,且无重复元素):

function binarySearch(array, value) {
    var low = 0;
    var high = array.length-1;
    while(low <= high) {
        var mid = Math.ceil((low+high)/2);
        if (value < array[mid]) {
            high = mid - 1;
        } else if (value > array[mid]) {
            low = mid + 1;
        } else {
            return mid;
        }
    }
    return -1;
}
复制代码

注意点:

  1. 循环退出条件:low<=high,不是low<high
  2. mid的取值:整数值、当low和high数值很大时,加和可能溢出。low+(high-low)>>1
  3. low和high的更新:需要+1和-1,如果直接low=mid可能死循环。如:hight=3,mid=3,而a[3]!=value时。

递归实现:

function binarySearch(array,low,high, value) {
    if (low > high) return -1;
    
    var mid = low + ((high-low)>>1);
    if (array[mid] > value) {
        return binarySearch(array,low, mid-1, value);
    } else if (array[mid] < value) {
        return binarySearch(array, mid+1, high, value);
    } else {
        return mid;
    }
}
复制代码
二分查找使用范围
  1. 二分查找依赖顺序表结构,即数组
  2. 针对有序数据,或者一次排序多次查找的情况。动态数据集不适用。
  3. 适用数据量大的情况,或者比较比较耗时(长字符串比较),需要减少比较次数的情况。

练习:求解平方根

// 求解整数n的平方根

// 牛顿迭代法求 f(n): n的平方根
// f(n+1) = (f(n)+k/f(n))/2;
// 假设f(1) = n/2 可以是任意数,尽量接近
// 当 |f(n+1)-f(n)|<0.00001时,可得结果f(n)
function squareRoot1(n) {
    var y = n/2;
    while(Math.abs((y+n/y)/2-y) >= 0.00001) {
        y = (y+n/y)/2;
    }
    return y;
}

// 二分法求平方根
// 整数n的平方根x x*x = n 则0<=x<=n的。因此可以转化为在0~n之间查找x,使得x*x=n,但因为有小数存在因此|x*x-n|<0.00001时,就算找到结果。
function squareRoot2(n) {
    var low = 0;
    var high = n;
    while (low <= high) {
        var mid = low+(high-low)/2;
        if (Math.abs(mid*mid-n) > 0.00001) {
            if (mid*mid > n) {
                high = mid;
            } else {
                low = mid;
            }
        } else {
            return [mid.toFixed(5), Math.sqrt(n)];
        }
    }
   
    return -1;

}
复制代码

转载于:https://juejin.im/post/5bed178ff265da612239ea15

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值