【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.mzph.cn/diannao/39436.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第4章:Electron主窗口与子窗口管理

4.1 创建主窗口 主窗口是 Electron 应用启动后显示的第一个窗口&#xff0c;通常用来承载应用的主界面。我们使用 BrowserWindow 类来创建主窗口。 4.1.1 创建主窗口的基础代码 // 引入 Electron 模块和 Node.js 的 path 模块 const { app, BrowserWindow } require(electr…

【动态规划 前缀和】2478. 完美分割的方案数

本文涉及知识点 划分型dp 动态规划汇总 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 LeetCode 2478. 完美分割的方案数 给你一个字符串 s &#xff0c;每个字符是数字 ‘1’ 到 ‘9’ &#xff0c;再给你两个整数 k 和 minLength 。 如…

【C++ Primer Plus学习记录】指针和const

可以用两种不同的方式将const关键字用于指针。第一种方法是让指针指向一个常量对象&#xff0c;这样就可以防止使用该指针来修改所指向的值&#xff0c;第二种方法是将指针本身声明为常量&#xff0c;这样可以防止改变指针指向的位置。 首先&#xff0c;声明一个指向常量的指针…

前后端防重复提交(续)

前文介绍过前后端防重复提交的基本场景&#xff0c;简单的情况是只发起一个异步请求&#xff0c;如果有多个异步请求怎么操作呢&#xff1f;这个要分情况看下。 如果是后端服务器的接口支持一次传递多个申请&#xff0c;那么可以将任务放进数组中&#xff0c;发往后端。这是最好…

074、Python 关于实例方法、静态方法和类方法

在Python中&#xff0c;类可以定义三种类型的方法&#xff1a;实例方法、静态方法和类方法。每种方法都有其特定的用途和调用方式。 实例方法&#xff08;Instance Methods&#xff09; 定义&#xff1a;实例方法是绑定到类实例上的方法。它们必须有一个名为self的隐式第一个参…

golang 1.22特性之for loop

背景 go1.22版本 for loop每轮循环都生成新的变量. 原谅: https://tip.golang.org/doc/go1.22 Previously, the variables declared by a “for” loop were created once and updated by each iteration. In Go 1.22, each iteration of the loop creates new variables, to …

【C++11】自己封装RAII类,有哪些坑点?带你了解移动语义的真相

文章目录 一、持有资源的类定义移动构造函数的要点1.普通内置类型与std::move2.常见的容器与std::move3.结构体&#xff1a;4.智能指针与std::move 参考 一、持有资源的类定义移动构造函数的要点 1.普通内置类型与std::move 在C中&#xff0c;std::move 主要用于对象的移动语…

Wireshark - tshark支持iptables提供数据包

tshark现在的数据包获取方式有两种&#xff0c;分别是读文件、网口监听&#xff08;af-packet原始套接字&#xff09;。两种方式在包获取上&#xff0c;都是通过读文件的形式&#xff1b;存在文件io操作&#xff0c;在专门处理大流量的情境下&#xff0c; 我们复用wireshark去做…

Windows编程上

Windows编程[上] 一、Windows API1.控制台大小设置1.1 GetStdHandle1.2 SetConsoleWindowInfo1.3 SetConsoleScreenBufferSize1.4 SetConsoleTitle1.5 封装为Innks 2.控制台字体设置以及光标调整2.1 GetConsoleCursorInfo2.2 SetConsoleCursorPosition2.3 GetCurrentConsoleFon…

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…

Redis的使用(二)redis的命令总结

1.概述 这一小节&#xff0c;我们主要来研究一下redis的五大类型的基本使用&#xff0c;数据类型如下&#xff1a; redis我们接下来看一看这八种类型的基本使用。我们可以在redis的官网查询这些命令:Commands | Docs,同时我们也可以用help 数据类型查看命令的帮助文档。 2. 常…

数据结构 - C/C++ - 串

字符处理 C 特性 C语言中字符串存储在字符数组中&#xff0c;以空字符\0结束。 字符串常量&#xff0c;const char* str "Hello"&#xff0c;存储在只读的数据段中。 布局 字符串在内存中是字符连续存储的集合&#xff0c;最后一个字符为空字符(ASCII值为0)&…

opencascade AIS_InteractiveContext源码学习7 debug visualization

AIS_InteractiveContext 前言 交互上下文&#xff08;Interactive Context&#xff09;允许您在一个或多个视图器中管理交互对象的图形行为和选择。类方法使这一操作非常透明。需要记住的是&#xff0c;对于已经被交互上下文识别的交互对象&#xff0c;必须使用上下文方法进行…

【问题已解决】Vue管理后台,点击登录按钮,会发起两次网络请求(竟然是vscode Compile Hero编译插件导致的)

问题 VueElement UI 做的管理后台&#xff0c;点击登录按钮&#xff0c;发现 接口会连续掉两次&#xff0c;发起两次网络请求&#xff0c;但其他接口都是正常调用的&#xff0c;没有这个问题&#xff0c;并且登录按钮也加了loading&#xff0c;防止重复点击&#xff0c;于是开…

搜索引擎常用语法

引号 (" "): 用双引号将词组括起来&#xff0c;搜索引擎将返回包含完全相同短语的结果。 示例&#xff1a;"人工智能发展趋势" 减号 (-): 在关键词前加上减号可以排除包含特定词语的结果。 示例&#xff1a;人工智能 -机器学习&#xff08;排除包含 “机器…

朴素贝叶斯解密:sklearn中的分类器工作原理

&#x1f4da; 朴素贝叶斯解密&#xff1a;sklearn中的分类器工作原理 在机器学习领域&#xff0c;朴素贝叶斯分类器因其简单、高效而广受欢迎。特别是在处理大量特征数据时&#xff0c;朴素贝叶斯表现出了卓越的性能。scikit-learn&#xff08;简称sklearn&#xff09;是Pyth…

JavaMySQL 学习(基础)

目录 Java CMD Java发展 计算机存储规则 Java学习 switch新用法&#xff08;可以当做if来使用&#xff09; 数组定义 随机数 Java内存分配 MySQL MySQL概述 启动和停止 客户端连接 数据模型 关系型数据库 SQL SQL通用语法 SQL分类 DDL--数据定义语言 数据库…

浏览器开发者工具辅助爬虫开发

文章目录 浏览器开发者工具辅助爬虫开发打开开发者工具使用Network面板分析请求数据示例步骤&#xff1a; 使用Elements面板查看和修改DOM结构示例步骤&#xff1a; 使用Console面板调试JavaScript代码示例步骤&#xff1a;示例代码&#xff1a;1. 输出日志信息2. 输出对象信息…

Vue 与 React 区别

Vue.js和React是现代Web开发中两种非常流行的前端框架&#xff0c;两者在**核心概念、组件以及生态系统扩展性**等方面存在区别。具体分析如下&#xff1a; 1. **核心概念** - **Vue**&#xff1a;Vue是一个渐进式JavaScript框架&#xff0c;它致力于视图层&#xff0c;易于上手…

左值右值, 左值引用右值引用,完美转发

一. 左值和右值 左值: 可以取地址的对象 右值: 不可以取地址的对象 double x1.0, y 2.0; 1; // 字面量, 不可取地址, 是右值 x y; // 表达式返回值, 不可取地址, 是右值 max(x, y); // 传值返回函数的返回值 (非引用返回)总结就是: 根据是否可以取地址来区分是左值还…