二分查找算法(非递归实现)及其使用示例

二分查找算法(非递归)

(1) 二分查找算法(非递归)介绍

  • 二分查找法只适用于从有序的数列中进行查找(比如数字和字母等),将数列排序后再进行查找
  • 二分查找法的运行时间为对数时间 O(㏒₂n) ,即查找到需要的目标位置最多只需要㏒₂n 步,假设从[0,99]的队列(100 个数,即 n=100)中寻到目标数 30,则需要查找步数为㏒₂100 , 即最多需要查找 7 次( 2^6 < 100 < 2^7)

(2)二分查找算法(非递归)代码实现

​ 数组 {1,3, 8, 10, 11, 67, 100}, 编程实现二分查找,要求使用非递归的方式完成

public class BinarySearchNoRecur {
    public static void main(String[] args) {
        //测试
        int[] arr = {1,3, 8, 10, 11, 67, 100};
        int index = binarySearch(arr, 100);
        System.out.println("index=" + index);//
    }

    //二分查找的非递归实现
    /**
     *
     * @param arr 待查找的数组, arr 是升序排序
     * @param target 需要查找的数
     * @return 返回对应下标,-1 表示没有找到
     */
    public static int binarySearch(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;
        while(left <= right) { //说明继续查找
            int mid = (left + right) / 2;
            if(arr[mid] == target) {
                return mid;
            } else if ( arr[mid] > target) {
                right = mid - 1;//需要向左边查找
            } else {
                left = mid + 1; //需要向右边查找
            }
        }
        return -1;
    }
}

二分法查找的使用

1、LeetCode162、寻找峰值

二分查找算法(非递归实现)及其使用示例_第1张图片

  • 分析

    看到进阶时要达到O(logN)的时间复杂度,其实就能想到使用二分法了,但是具体该如何使用呢?要有峰值的话,主要有一下三种情况:

    • 整个数列单调递减
    • 整个数列单调递增
    • 数列先增后减,相当于有一个极大值

    如果使用线性查找的方法的话,其实就是一句话:nums[i]>nums[i+1]。但是如何使用到二分呢?

    • 对比线性查找的话,线性查找一个目标值的话,使用的是nums[i]==target;此时针对峰值的话,是nums[i]>nums[i+1]

    • 如果使用二分法的话,使用二分的话,对比上面三种情况的话

      • 如果nums[mid]>nums[mid+1],说明峰值在左边,right=mid;
      • 如果nums[mid]<=nums[mid+1],说明峰值在右边,left=mid+1

      此时,对比二分查找target的话,

      • 如果nums[mid]>target,说明目标值在左边,right=mid;
      • 如果nums[mid]
  • 代码实现

    //线性扫描
    public class Solution {
        public int findPeakElement(int[] nums) {
            for (int i = 0; i < nums.length - 1; i++) {
                if (nums[i] > nums[i + 1])
                    return i;
            }
            return nums.length - 1;
        }
    }
    //时间复杂度:O(n)。 我们对nums只进行一次遍历。
    //空间复杂度:O(1)。 只使用了常数空间。
    
    //迭代二分查找
    public class Solution {
        public int findPeakElement(int[] nums) {
            int l = 0, r = nums.length - 1;
            while (l < r) {
                int mid = (l + r) / 2;
                if (nums[mid] > nums[mid + 1])
                    r = mid;
                else
                    l = mid + 1;
            }
            return l;
        }
    }
    //时间复杂度:O(log2(n))。 每一步都将搜索空间减半
    //空间复杂度:O(1)。 只使用了常数空间。
    

你可能感兴趣的:(算法,数据结构,二分法)