zoukankan      html  css  js  c++  java
  • 二分查找

    二分查找

    二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

    二分查找从思路上来说并不复杂,但是在细节上有很多需要注意的地方。

    1.二分查找框架

    int binarySearch(int[] nums, int target) {
        int left = 0, right = ...;
    
        while(...) {
            //这里使用left+(left+right)/2而不使用(left+right)/2是为了避免left+right结果太大导致溢出
            int mid = left+(right-left) / 2;
            if (nums[mid] == target) {
                ...
            } else if (nums[mid] < target) {
                left = ...
            } else if (nums[mid] > target) {
                right = ...
            }
        }
        return ...;
    }
    

    2.寻找一个数(基本二分搜索)

    在一个有数排列中寻找一个数

    int binarySearch(int[] nums, int target) {
        int left = 0, right = nums.length-1;
    
        while(right>=left) {
            //这里使用left+(left+right)/2而不使用(left+right)/2是为了避免left+right结果太大导致溢出
            int mid = left+(right-left) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid+1;
            } else if (nums[mid] > target) {
                right = mid-1;
            }
        }
        return -1;
    }
    

    如果排列是一个数组为[1,2,2,2,3,3,4],怎样找到数组最左侧或者最右侧的2呢?

    这里我们要引出左侧边界二分搜索和右侧边界二分搜索

    3.左侧边界二分搜索

    主要是要理解在左侧边界搜索时,target<=nums[mid]时,right=mid-1;这一步

    int left_bound(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] >= target) {
                right = mid - 1;
            } 
        }
        // 最后要检查 left 越界的情况
        if (left >= nums.length || nums[left] != target)
            return -1;
        return left;
    }
    

    4.右侧边界二分搜索

    同理,理解target>=nums[mid]时,left=mid+1;

    int right_bound(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] <= target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } 
        }
        // 最后要检查 right 越界的情况
        if (right < 0 || nums[right] != target)
            return -1;
        return right;
    }
    
  • 相关阅读:
    规格说明书-----吉林1日游
    每周代码及工作总结(第九周)
    评论beta发布
    每周代码及工作总结(第八周)
    半年之后没啥意思,开个博客
    本周例行报告
    final发布评论Ⅱ
    课堂final发布
    本周例行报告
    回顾
  • 原文地址:https://www.cnblogs.com/ruonan1997/p/15262631.html
Copyright © 2011-2022 走看看