【ARTS】【LeetCode-704】二分查找算法

目录

前言

什么是ARTS?

算法

力扣704题

二分查找

基本思想:

二分查找算法(递归的方式):

经典写法(找单值):

代码分析:

经典写法(找数组即多个返回值)

代码分析

经典题目

题目描述:

官方题解

深入思考

模版一 (相错终止/左闭右闭)

相等返回情形

情形1 (大于等于)

情形2 (大于)

情形3 (小于等于)

情形4 (小于)

模版二 (相等终止/左闭右开)

相等返回情形

情形1 (大于等于)

情形2 (大于)

情形3 (小于等于)

情形4 (小于)

从「y总模版」到「模版二」之「左开右闭」

相等返回情形

情形1 (大于等于)

情形2 (大于)

情形3 (小于等于)

情形4 (小于)

模版三 (相邻终止/左开右开)

相等返回情形

情形1 (大于等于)

情形2 (大于)

情形3 (小于等于)

情形4 (小于)

参考资料:


前言

仅做学习使用,侵删

什么是ARTS?

算法(Algorithm): 每周至少一道LeetCode算法题,加强编程训练和算法学习

阅读(Review): 阅读并点评至少一篇英文技术文章,提高英文水平

技巧 (Tip):学习至少一个技术技巧,总结、归纳日常工作中遇到的知识点

分享(Share):分析一篇有关点和思考的技术文章,建立影响力,输出价值观

算法

力扣704题

一道经典的二分查找题目

链接:704. 二分查找 - 力扣(LeetCode)

二分查找

基本思想:

二分查找算法(递归的方式):
  1. 创建一个查找算法,参数列表有left,right,findValue,array
  2. 创建一个变量mid,通过left和right获取mid
  3. 通过对mid的比较,决定递归方向
  4. 最后判断是否能找到
📌

请注意,所有的二分查找算法都是建立在数组有序的基础上的,如果带查找序列是无序序列,不能用二分查找算法,只能使用其他查找算法,谨记!

经典写法(找单值):

public static int binarySearchSingle(int[] array,int left,int right,int findValue) {
        if(left > right || findValue > array[length-1]) {
            return -1;
        }
        var mid = left + 1/2*(right - left);
        var midValue = array[mid];
        if(findValue > midValue) {
            return binarySearchSingle(array,mid+1,right,findValue);
        }else if(findValue < midValue) {
            return binarySearchSingle(array,left,mid-1,findValue);
        }else {
            return mid;
        }
    }
代码分析:
  1. left是左索引,right是右索引,应该一开始就被赋值为0与array.length-1(因为带查找的值在他们两个索引之间,即[left,right]区间内有带查找元素)
  2. findValue是待查找的值,array是带查找的数组
  3. 二分查找法顾名思义是折半,所以mid = 1/2(left + right) = left + 1/2*(right - left)

注意:后面的表达式非常的重要,是折半查找发的关键

  1. 将mid下标对应的值放入midValue

情况:

  1. 如果midValue大于findValue,由于有序,说明待查找的元素在mid右边且不为mid,所以得出了[mid+1,right]的范围内有带查找元素,故left = mid+1
  2. 如果midVvalue小于findValue,由于有序,说明带查找的元素在mid左边且不为mid,所以得出了[left,mid-1]的范围内有带查找元素,故right = mid-1
  3. 如果midValue = findValue,说明找到了该元素,直接返回mid即可,mid是下标
  4. 如果left > right,由于没有这样的区间(即区间左边必须小于右边的值),说明找不到,直接返回-1
  5. 如果findValue大于列表的最后一个值,由于有序,最后一个值为最大值,说明列表里面不可能有与findValue相同的值,直接返回-1

经典写法(找数组即多个返回值)

 public static List<Integer> binarySearchMore(int[] array,int left,int right,int findValue) {
        if(left > right || findValue > array[length-1]) {
            return new ArrayList<Integer>();
        }
        var mid = (left + right)/2;
        var midValue = array[mid];
        if(findValue > midValue) {
            return binarySearchMore(array,mid+1,right,findValue);
        }else if(findValue < midValue) {
            return binarySearchMore(array,left,mid-1,findValue);
        }else {
            var list = new ArrayList<Integer>();
            list.add(mid);
            var temp = mid - 1;
            while(temp > 0 && array[temp] == findValue) {
                list.add(temp--);
            }
            temp = mid + 1;
            while (temp < array.length && array[temp] == findValue) {
                list.add(temp++);
            }
            return list;
 
        }
代码分析
  1. 注意:由于其他代码都一样,我们重点分析一下else里面的代码
  2. 当程序进入else时,说明找到了该元素,由于我们要实现多元素返回,我们可以借助集合,故我们要new一个ArrayLsit<Integer>
  3. 先将该元素add进去集合中
  4. 创建一个辅助索引temp,赋值为mid-1(目的:向左遍历)
  5. 通过while循环,如果temp>0(防止数组下标越界异常),且array[temp] = findValue,说明此元素也是我们要找的元素,添加入集合中
  6. 如果while布尔表达式为false,说明temp遍历到了最左边或是不相等,由于列表的有序性,如果不相等,则前面的元素一定比midValue小,不可能再有带查找的元素,直接结束向左遍历
  7. temp赋值为mid+1(目的:向右遍历)
  8. 同理5~6
  9. 最后返回list即可
  10. 特别注意的是,如果找不到,我们返回一个空的集合,所以在最前面new了一个空集合

经典题目

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


示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
 

提示:

你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。
官方题解
class Solution {
    public int search(int[] nums, int target) {
        int left = 0,right = nums.length - 1;
        while (left <= right){
            int mid = (right - left) / 2 +left;
            int num = nums[mid];
            if (num == target) {
                return mid;
            } else if (num > target) {
                right = mid - 1;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值