【LeetCode】十、二分查找法:寻找峰值 + 二维矩阵的搜索

文章目录

  • 1、二分查找法 Binary Search
  • 2、leetcode704:二分查找
  • 3、leetcode35:搜索插入位置
  • 4、leetcode162:寻找峰值
  • 5、leetcode74:搜索二维矩阵

1、二分查找法 Binary Search

找一个数,有序的情况下,直接遍历找,时间复杂度为O(n),用二分法,一半一半的砍着找,则时间复杂度为O(log n),更优

在这里插入图片描述

核心:左、中、右三个指针的移动

2、leetcode704:二分查找

在这里插入图片描述

注意下面对中间指针的求法,不写 (l + r ) / 2,写成 l + (r - l) / 2,二者通分后值一样,但l + r可能超出int的最大值,后者这种写法则可规避这个问题。且 除二可以改为位运算 >> 1,其快于除法运算,注意右移的运算优先级很低,要加括号(a + b >> c 会首先执行加法 a + b,然后将结果右移 c 位

public class P704 {

    public static int binarySearch(int[] array, int value) {
        if (array == null || array.length == 0) {
            return 0;
        }
        int left = 0;
        int right = array.length - 1;
        int mid;
        while (left <= right) {
            mid = left + (right - left) / 2;
            if (array[mid] > value) {
                // 右边半截不要了
                right = mid - 1;
            } else if (array[mid] < value) {
                // 左边半截不要了
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
}

测试:

public class P704 {
    public static void main(String[] args) {
        int[] num = {-1, 0, 3, 5, 9, 12};
        System.out.println(binarySearch(num, 9));
        System.out.println(binarySearch(num, 10));
    }

}

在这里插入图片描述

3、leetcode35:搜索插入位置

在这里插入图片描述
第一个想法是:先普通的二分查找value,返回-1后,说明不存在,那就再遍历这个数组,用双指针,当p1的值 < value && p2的值 > value时,return p1 + 1,但这样应该是复杂了

在这里插入图片描述

换个想法,只需调整下普通的二分查找:这题要求找值target,有就返回下标索引,无就返回插入后的下标索引,因此,这题要找第一个大于等于target的值的下标索引,如果有等于target的,那返回其下标,如果不存在,那就要插入到第一个比target大的值的位置,第一个大的值的下标则往后移动一位。

在这里插入图片描述

public class P35 {
    
    public static int searchOrInsert(int[] array, int target) {
        if (array == null || array.length == 0) {
            return 0;
        }
        int left = 0;
        int right = array.length - 1;
        int ans = array.length;
        while (left <= right) {
            int mid = ((right - left) >> 1) + left;
            if (target == array[mid]) {
                // 如果有,直接返回
                return mid;
            } else if (target < array[mid]) {
                // 如果mid大于target,存一下mid的值
                // 此时mid是大于target的值,但不一定是第一个大于target的值
                ans = mid;
                right = mid - 1;
            } else {
                // 左指针右移,说明target很大,极限时,插入到末尾,此时return array.length即末尾
                left = mid + 1;
            }
        }
        return ans;
    }
}

4、leetcode162:寻找峰值

在这里插入图片描述

一头一尾是负无穷,所以,即使是1,2,3,4这个输入,也有峰值:4

在这里插入图片描述

m+1 > m时,m+1到right之间一定有一个峰值,不论m的左侧是单增、单减、波浪起伏。此时可把左指针移动到m+1的位置,减少搜索范围。

public class P162 {

    public static int getPeak(int[] array) {
        if (null == array || array.length == 0){
            return -1;
        }
        int left = 0;
        int right = array.length - 1;
        // 这儿不能允许left==right,否则当left=right=末尾元素时,mid也就是末尾元素,mid+1就越界了
        while (left < right) {
            int mid = left + ((right - left) >> 1);
            //说明mid和mid+1两个点,从左到右是下降的,mid自身或者mid的左边可能有峰值
            if (array[mid] > array[mid + 1]) {
                right = mid;
            } else {
                // 一定有个峰值出现在mid+1到right之间
                left = mid + 1;
            }
        }
        return left;
    }
}

5、leetcode74:搜索二维矩阵

如题,这样特点的矩阵,本身就是递增的,如图中的1、3、5、7、10、11、16……

在这里插入图片描述

在有序的集合里找一个数字,可以二分查找。但现在虽然有序,却不是集合,是一个二维数组,那把矩阵拍平后就是一个简单的二分查找了。把这个矩阵(二维数组)拍平有两种思路:

  • 直接遍历二维数组,把每个元素装入一位数组,但这样得两层for,时间复杂度太高
  • 思想上拍平,将二维数组的索引,和一维数组建立联系

考虑将二维数组的索引(x,y)转为一维的索引i,。关于二维索引和一维索引的相互转换,发现:

在这里插入图片描述
将二维索引(x,y)和一维索引 i 标出来,得出:一维索引的坐标 i = x * 列总数 + y

如上面总列数为4(0,0)对应的一维坐标正好是 0 * 4 + 0 = 0

如此,不用遍历二维数组,就可将矩阵的每个数都对应一个一维坐标。二分法时,起始左指针 = 0, 右指针 = 行数 × 列数 - 1(即总元素数),计算出mid后,无法根据mid索引在二维数组中取值,需要将一维坐标再倒回去,x = i / 列总数 ,y = i % 总列数

public class P74 {

    public boolean matrixSearch(int[][] matrix, int target) {
        if (null == matrix || matrix.length == 0) {
            return false;
        }
        // 行数
        int row = matrix.length;
        // 列数
        int col = matrix[0].length;
        // 左右指针起始位置
        int left = 0;
        int right = row * col - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            // 无法根据一维的mid索引在二维数组中取值,需要将一维坐标再倒回去
            // x = i / 列总数 ,y = i % 总列数
            int element = matrix[mid / col][mid % col];
            if (target == element) {
                return true;
            } else if (target < element) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }

        }
        return false;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/765675.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从零开始实现大语言模型(二):文本数据处理

1. 前言 神经网络不能直接处理自然语言文本&#xff0c;文本数据处理的核心是做tokenization&#xff0c;将自然语言文本分割成一系列tokens。 本文介绍tokenization的基本原理&#xff0c;OpenAI的GPT系列大语言模型使用的tokenization方法——字节对编码(BPE, byte pair en…

Apache POI、EasyPoi、EasyExcel

目录 ​编辑 &#xff08;一&#xff09;Apache PoI 使用 &#xff08;二&#xff09;EasyPoi使用 &#xff08;三&#xff09;EasyExcel使用 写 读 最简单的读​ 最简单的读的excel示例​ 最简单的读的对象​ &#xff08;一&#xff09;Apache PoI 使用 &#xff08;二&…

33 包装器

c11 也叫适配器。c中的function本质是一个类模板&#xff0c;也是一个包装器 为什么需要fuction呢&#xff1f; 当一个类型既可以是函数指针&#xff0c;也可以是仿函数和lambda比倒是&#xff0c;函数指针的类型不好理解&#xff0c;仿函数写起来麻烦&#xff0c;lambda无法拿…

2024年工程项目管理者的软件指南:11款必试进度管理工具

本文将分享11个值得关注的工程项目进度管理软件&#xff1a;Worktile、Fieldwire、Procore、Buildxact、InEight、Contractor Foreman、Housecall Pro、ClickUp、RedTeam Go、Visual Planning、B2W Schedule。 在竞争激烈的建筑行业&#xff0c;工程项目的进度管理是项目成功的…

Linux 实现自定义系统调用,支持参数和结果返回

本文实现一个简单的系统调用实现&#xff0c;支持输入字符串参数&#xff0c;并返回一个结果字符串。 以下是验证步骤&#xff1a; 1. 添加系统调用编号 试验使用的是 x86_64 架构的 Linux 内核。 找到并编辑 arch/x86/entry/syscalls/syscall_64.tbl 文件&#xff0c;在文件…

编写动态库

1.创建库.c .h文件 2.编写Makefile文件 3.make之后形成.so文件 4.make output,形成mylib 5.把mylib拷贝到test里面 mv mylib /test 6.编译 gcc main.c -I mylib/include -L mylib/lib -lmymethod形成a.out 但是直接执行会出现以下问题 很显然没有找到动态库 7.解决加载找不…

主干网络篇 | YOLOv8改进之引入YOLOv10的主干网络 | 全网最新改进

前言:Hello大家好,我是小哥谈。YOLOv10是由清华大学研究人员利用Ultralytics Python软件包开发的,它通过改进模型架构并消除非极大值抑制(NMS)提供了一种新颖的实时目标检测方法。这些优化使得模型在保持先进性能的同时,降低了计算需求。与以往的YOLO版本不同,YOLOv10的…

DFS练习

105 从前序与中序遍历序列构造二叉树 import java.util.HashMap; import java.util.Map;class TreeNode {int val;TreeNode left;TreeNode right;public TreeNode(int val) {this.val val;} }public class Letcode105 {public TreeNode bulidTree(int[] preOrder, int[] inOrd…

c++将一个复杂的结构体_保存成二进制文件并读取

在 C 中&#xff0c;可以将复杂的结构体保存到二进制文件中&#xff0c;并从二进制文件中读取它。为了实现这一点&#xff0c;你可以使用文件流库 <fstream>。以下是一个示例&#xff0c;展示如何将一个复杂的结构体保存到二进制文件中&#xff0c;并从二进制文件中读取它…

去中心化经济的革新:探索Web3的新商业模式

随着区块链技术的发展&#xff0c;Web3正逐渐成为全球经济和商业模式的关键词之一。Web3不仅仅是技术的革新&#xff0c;更是对传统中心化商业模式的挑战和重构。本文将深入探讨Web3背后的概念、关键技术以及其带来的新商业模式&#xff0c;带领读者走进这一新兴领域的深度分析…

python如何输出list

直接输出list_a中的元素三种方法&#xff1a; list_a [1,2,3,313,1] 第一种 for i in range(len(list_a)):print(list_a[i]) 1 2 3 313 1 第二种 for i in list_a:print(i) 1 2 3 313 1 第三种&#xff0c;使用enumerate输出list_a方法&#xff1a; for i&#xff0c;j in enum…

中日区块链“大比拼”!中国蚂蚁加大区块链押注资本!日本索尼进军加密货币市场!

科技巨头在区块链和加密货币领域的动作越来越频繁。近期&#xff0c;中国金融科技巨头蚂蚁集团进一步加大了在区块链业务上的投资&#xff0c;而日本电子科技巨头索尼集团则正式进军加密货币交易领域。这些举措反映了两国对于区块链和加密资产领域的不同态度和布局。 蚂蚁集团加…

游戏AI的创造思路-技术基础-关于艾宾浩斯遗忘曲线的迷思

对于艾宾浩斯遗忘曲线和函数&#xff0c;我一直都有小小的迷思&#xff0c;总想实验下用艾宾浩斯函数来替换sigmoid函数作为激活函数&#xff0c;打造更接近人类的AI算法&#xff0c;这篇文章旨在讨论下 目录 3.10. 艾宾浩斯曲线 3.10.1. 定义 3.10.1.1. 曲线计算公式 3.10…

【QT】常用控件|widget|QPushButton|RadioButton|核心属性

目录 ​编辑 概念 信号与槽机制 控件的多样性和定制性 核心属性 enabled geometry ​编辑 windowTiltle windowIcon toolTip styleSheet PushButton RadioButton 概念 QT 控件是构成图形用户界面&#xff08;GUI&#xff09;的基础组件&#xff0c;它们是实现与…

维护Nginx千字经验总结

Hello , 我是恒 。 维护putty和nginx两个项目好久了&#xff0c;用面向底层的思路去接触 在nginx社区的收获不少&#xff0c;在这里谈谈我的感悟 Nginx的夺冠不是偶然 高速:一方面&#xff0c;在正常情况下&#xff0c;单次请求会得到更快的响应&#xff1b;另一方面&#xff0…

深入解析:Java爬虫的本质是什么?

深入解析&#xff1a;Java爬虫的本质是什么&#xff1f; 引言&#xff1a; 随着互联网的快速发展&#xff0c;获取网络数据已成为许多应用场景中的重要需求。而爬虫作为一种自动化程序&#xff0c;能够模拟人类浏览器的行为&#xff0c;从网页中提取所需信息&#xff0c;成为了…

递归算法练习

112. 路径总和 package Tree;import java.util.HashMap; import java.util.Map;class TreeNode {int val;TreeNode left;TreeNode right;public TreeNode(int val) {this.val val;} }/*** 求 树的路径和* <p>* 递归 递减* <p>* 询问是否存在从*当前节点 root 到叶…

【Python】MacBook M系列芯片Anaconda下载Pytorch,并开发一个简单的数字识别代码(附带踩坑记录)

文章目录 配置镜像源下载Pytorch验证使用Pytorch进行数字识别 配置镜像源 Anaconda下载完毕之后&#xff0c;有两种方式下载pytorch&#xff0c;一种是用页面可视化的方式去下载&#xff0c;另一种方式就是直接用命令行工具去下载。 但是由于默认的Anaconda走的是外网&#x…

3D Gaussian Splatting代码中的forward和backward两个文件代码解读

3dgs代码前向传播部分 先来讨论一下glm&#xff0c;因为定义变量的时候用到了这个。 glm的解释 glm 是指 OpenGL Mathematics&#xff0c;这是一个针对图形编程的数学库。它的全称是 OpenGL Mathematics (GLM)&#xff0c;主要用于 OpenGL 的开发。这个库是基于 C 的模板库&…

heic格式转化jpg,手把手教你将heic转换成jpg【办公必备】

一、什么是heic heic格式是一种高效的图片格式&#xff0c;它可以在较小的文件大小下提供高质量的图片。 二、如何打开heic 然而&#xff0c;这种图片因其格式的特殊性&#xff0c;在实际应用中仍存在一些问题&#xff1a;压缩效果可能不够理想&#xff0c;一些老旧的软件和设…