力扣704/35/34:二分查找

考虑到线性查找法的时间复杂度较高(O(n)), 我们可以选择使用二分查找算法.

二分查找算法只适用于有序数组(线性查找不需要满足该前提), 其时间复杂度为O(logn), 我们可以选择两种方式来完成二分查找算法.

要求 : 给定一个有序整形数组, 在该数组中, 找到目标值target, 如果找到, 则返回其在数组中的索引, 否则返回-1.

(1)方法1 : 指针左闭右闭i, j----> 推导出循环条件 : i <= j

java 复制代码
public static int BinarySearch_1(int[] arr, int target) {
        int i = 0;
        int j = arr.length - 1;
        //设置指针和初值
        while (i <= j) {
            int mid = i + (j - i) / 2;
            if (arr[mid] == target) {
                return mid;
            } else if (arr[mid] < target) {
                i = mid + 1;
            } else {
                j = mid - 1;
            }
        }
        return -1;
    }

方式2 : 指针左闭右开[i, j) -----> 推导出循环条件 : i < j

java 复制代码
public static int BinarySearch_2(int[] arr, int target) {
        int i = 0;
        int j = arr.length;
        while (i < j) {
            int mid = i + (j - i) / 2;
            if (arr[mid] > target) {
                j = mid;
            } else if (arr[mid] < target) {
                i = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }

test :

java 复制代码
@Test
    public void test1() {
        int[] arr = {1, 4, 6, 9, 11, 15, 57};
        int target = 9;
        int index1 = BinarySearch_1(arr, target);
        System.out.println("索引处是" + index1);
        int index2 = BinarySearch_2(arr, target);
        System.out.println("索引处是" + index2);

    }

控制台 : 
索引处是3
索引处是3

而对于有重复性元素的数组来说, 查找值恰好为该重复的元素值, 上面两种方式返回的索引即为第一次被查找到的索引位置,.

test :

java 复制代码
@Test
    public void test1() {
        int[] arr = {9, 9, 9, 9, 9, 9};
        int target = 9;
        int index1 = BinarySearch_1(arr, target);
        System.out.println("索引处是" + index1);
        int index2 = BinarySearch_2(arr, target);
        System.out.println("索引处是" + index2);

    }

控制台 : 
索引处是2
索引处是3

如果我们要求返回的索引是重复元素最左边的位置的索引, 即如上, 应返回索引0.我们应该对算法做出怎样的变化呢?

java 复制代码
public static int BinarySearch_3(int[] arr, int target) {
        int i = 0;
        int j = arr.length - 1;
        //设置候选索引
        int cadicate = -1;
        int mid = i + (j - i) / 2;
        while (i <= j) {
            mid = i + (j - i) / 2;
            if (arr[mid] > target) {
                j = mid - 1;
            } else if (arr[mid] < target) {
                i = mid + 1;
            } else {
                //如果arr[mid] == target, 并不退出循环, 而是更新候选值, 继续向左排查
                cadicate = mid;
                j = mid - 1;
            }
        }
        return cadicate == -1 ? -1 : cadicate;
    }

test :

java 复制代码
@Test
    public void test1() {
        int[] arr = {1, 4, 7, 7, 7, 7,  8, 10};
        int target = 7;
        int index3 = BinarySearch_3(arr, target);
        System.out.println("索引处是" + index3);

    }

控制台 : 
索引处是2

上述代码完成了返回了最左边的元素的索引, 如果我们想要得到最右边的元素的索引, 应该怎么办呢?非常简单, 只需要在else语句处略微改动.

java 复制代码
else {
      //如果arr[mid] == target, 并不退出循环, 而是更新候选值, 继续向右排查
      cadicate = mid;
      i = mid + 1;
}

test :

java 复制代码
@Test
    public void test1() {
        int[] arr = {1, 4, 7, 7, 7, 7, 7, 8, 10};
        int target = 7;
        int index4 = BinarySearch_4(arr, target);
        System.out.println("索引处是" + index4);
    }

控制台 : 
索引处是6
相关推荐
丘山一郎8 小时前
Spring 中的IOC控制反转 和DI依赖注入
java·后端·spring
码视野8 小时前
基于 Spring Boot + Vue3 的【大学英语四六级 (CET-4/6) 作文智能评分与句式润色系统】设计与实现(含PRD/三端高保真源码/大屏)
java·前端·人工智能·spring boot·后端·vue3
MetaLite8 小时前
Spring-AOP自调用为什么失效-AopContext真能解决吗
java·后端·spring
大模型码小白8 小时前
AI 对话流性能调优:万级消息的虚拟滚动落地
java·大数据·前端·javascript·人工智能·算法·机器学习
许彰午9 小时前
14-字段级SM4加密与SM2签名
java·低代码·架构
许彰午10 小时前
13-describe元数据输出
java·低代码·架构·状态模式
用户37215742613511 小时前
Java 设置 Word 文档编辑限制并允许指定区域编辑
java
船厂电气自动化ai大模型11 小时前
AI大模型与数学·第57课 傅里叶全套工具链综合实战:串联级数/连续变换/DFT/FFT,图像、音频、扩散模型完整例题
数据结构·人工智能·深度学习·算法·机器学习
wuyk55511 小时前
从零吃透Modbus通信|第3章:STM32 Modbus RTU主机
服务器·开发语言·网络·数据结构·stm32·单片机·嵌入式硬件
宠友信息11 小时前
社区类源码开发实践中的仿小红书系统技术要点分析
java·spring boot·redis·mysql·uni-app·vue·内容运营