基础算法-查找|二分查找

287 阅读1分钟

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

二分查找基础

二分查找,在很多场景里都会使用到,比如操作系统,MySQL,Hadoop等

  • 在有序的数组A中找到给定的数据。操作的数据集是有序的
  • 二分查找能应用于任何类型的数据,搜索的集合是相对静态的数据集

面试题

题目1:有序数组中查找目标值

ary = [1, 3, 4, 9, 11, 15, 19, 20,25],target = 8 使用二分查找的方式判断是否是否存在目标数值。

解题思路

二分查找,将有序数据集进行对半分割,并检查每个分区的中间元素,不断循环直到没有区间范围。这个区间范围通过left和right 2个变量来控制。

首先,定义一个区间[left, right] (left :首部位置,right:尾部位置) 开闭原则,我们需要定位的数据是在该区间范围内

第一轮:1, 3, 4, 9, 11, 15, 19, 20,25 left=0 ,right=8,mid=4

ary[mid] > target ,那么 right = mid-1=3

第二轮:1, 3, 4, 9, 11, 15, 19, 20,25 left =0 right = 3,mid= 1

ary[mid] <target,那么 left = mid+1 = 2

第三轮:1, 3, 4, 9, 11, 15, 19, 20,25 left = 2 right = 3 mid=2

left从左向右移,right从右向左移。一旦在middle处找到目标,查找将停止;如果没有找到目标,left和right将重合。

JavaScript 实现

function erfenSearch(ary, target) {
    if (ary.length ==0) return false;
​
    let left = 0, right = ary.length;
    while (left < right) {
        let mid = Math.floor((left + right) / 2);
        if(ary[mid] == target){
            return true;
        } else if (ary[mid] > target) {
            right = mid - 1;
        } else  if (ary[mid] < target)  {
            left = mid + 1;
        }
​
    }
    return false;
}

复杂度分析:在实行二分查找时,由于每次我们都会扔掉一半的数据,所以总共只需要 O(lgn)的时间复杂度,空间复杂度是 O(1)。

题目2:查找旋转数组的最小元素(存在重复项)

1, 2, 3, 4, 5的旋转数组为:3, 4, 5, 1, 2要查询找到数组中的最小元素

解题思路:

通过设置三个标志位left,right,mid来减少查询长度。定义3,4,5为原序序列;1,2为翻转子序列。

如果中间元素ary[mid]小于左边元素ary[left],那么证明,中间元素属于翻转子序列。此时最小元素存在于标志位[left ,mid)之间;同理可得,当中间元素大于左边元素时,最小元素存在于标志位[mid,right)直接。

JavaScript 实现

// 寻找最小元素
function findMin(ary) {
    let len = ary.length;
    if(len == 0)
        return -1;
    let left = 0, right = len - 1, mid;
    while(left < right){
        mid = left + (right - left) / 2;
        if(ary[mid] > ary[right])
            left = mid + 1;
        else if(ary[mid] < ary[right])
            right = mid;
        else
            right--;
    }
    return ary[left];
}