【算法题】三道题理解算法思想——二分查找算法

2024-03-31 01:52

本文主要是介绍【算法题】三道题理解算法思想——二分查找算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

二分查找算法 

        本篇文章中会带大家从零基础到学会利用二分查找的思想解决算法题,我从力扣上筛选了三道题,难度由浅到深,会附上题目链接以及算法原理和解题代码,希望大家能坚持看完,绝对能有收获,大家有更好的思路也欢迎大家在评论区交流啊!

  

文章顺序:

题目链接=》算法原理=》代码呈现

思想总结:

在某种判断条件下将区间⼀分为⼆,然后舍去其中⼀个区间,然后再另⼀个区间内查找。
需要注意的是二分查找算法不是只可以在有序的的数组中使用,只要一组数据在某个值的前后性质具有单调性都可以使用,也就是具有二段性。

 1.二分查找

题目链接

https://leetcode.cn/problems/binary-search/

算法思路

。定义 left right 指针,分别指向数组的左右区间。
。找到待查找区间的中间点 mid ,找到之后分三种情况讨论:
  1. arr[mid] == target 说明正好找到,返回 mid 的值;
  2. arr[mid] > target 说明 [mid, right] 这段区间都是⼤于 target 的,因此舍去右边区间,在左边 [left, mid -1] 的区间继续查找,即让 right = mid -1 ,然后重复 2 过程;
  3. arr[mid] < target 说明 [left, mid] 这段区间的值都是⼩于 target 的,因此舍去左边区间,在右边 [mid + 1, right] 区间继续查找,即让 left = mid +1 ,然后重复 2 过程;
。当 left right 错开时,说明整个区间都没有这个数,返回 -1

代码呈现

class Solution {public int search(int[] nums, int target) {int left=0;int right=nums.length-1;while(left<=right){int mid=(left+right)/2;if(target==nums[mid]){return mid;}else if(target>nums[mid]){left=mid+1;}else{right=mid-1;}}return -1;}
}

 2.在排序数组中查找元素的第一个和最后一个位置

题目链接

https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/description/

算法思路

       ⽤的还是⼆分思想,就是根据数据的性质,在某种判断条件下将区间⼀分为⼆,然后舍去其中⼀个区间,然后再另⼀个区间内查找;
          为⽅便叙述,⽤ x 表⽰该元素, resLeft 表⽰左边界, resRight 表⽰右边界。
寻找左边界思路:
1. 寻找左边界:
         。 我们注意到以左边界划分的两个区间的特点:
                 ▪ 左边区间 [left, resLeft - 1] 都是⼩于 x 的;
                 ▪ 右边区间(包括左边界) [resLeft, right] 都是⼤于等于 x 的;
2.  因此,关于 mid 的落点,我们可以分为下⾯两种情况:
         。 当我们的 mid 落在 [left, resLeft - 1] 区间的时候,也就是 arr[mid] < target 。说明 [left, mid] 都是可以舍去的,此时更新 left mid + 1 的位置,继续在 [mid + 1, right] 上寻找左边界;
         。 mid 落在 [resLeft right] 的区间的时候,也就是 arr[mid] >= target 。说明 [mid+1,right] (因为 mid 可能是最终结果,不能舍去)是可以舍去的,此时更新 right mid 的位置,继续在 [left, mid] 上寻找左边界;
3.  由此,就可以通过⼆分,来快速寻找左边界;
注意:这⾥找中间元素需要向下取整。
因为后续移动左右指针的时候:
  • 左指针: left = mid + 1 ,是会向后移动的,因此区间是会缩⼩的;
  • 右指针: right = mid ,可能会原地踏步(⽐如:如果向上取整的话,如果剩下 1,2 两个元素, left == 1 right == 2 mid == 2 。更新区间之后, leftrightmid 值没有改变,就会陷⼊死循环)。

因此⼀定要注意,当 right = mid 的时候,要向下取整。

寻找右边界思路:
1.  寻右左边界:
        ◦ resRight 表⽰右边界;
        ◦ 我们注意到右边界的特点:
               ▪ 左边区间 (包括右边界) [left, resRight] 都是⼩于等于 x 的;
               ▪ 右边区间 [resRight+ 1, right] 都是⼤于 x 的;
2.  因此,关于 mid 的落点,我们可以分为下⾯两种情况:
        ◦ 当我们的 mid 落在 [left, resRight] 区间的时候,说明 [left, mid - 1]( mid 不可以舍去,因为有可能是最终结果) 都是可以舍去的,此时更新 left mid的位置;
        ◦ 当mid落在 [resRight+ 1, right] 的区间的时候,说明 [mid, right] 内的元素是可以舍去的,此时更新 right mid - 1 的位置;
3.  由此,就可以通过⼆分,来快速寻找右边界;
注意:这⾥找中间元素需要向上取整。
因为后续移动左右指针的时候:
  • 左指针: left = mid ,可能会原地踏步(⽐如:如果向下取整的话,如果剩下 1,2 两个元素, left== 1 right == 2mid == 1 。更新区间之后, leftrightmid 的值没有改变,就会陷⼊死循环)。
  • 右指针: right = mid - 1 ,是会向前移动的,因此区间是会缩⼩的;
因此⼀定要注意,当 right = mid 的时候,要向下取整。

代码呈现

class Solution {public int[] searchRange(int[] nums, int target) {int n=nums.length;int left=0;int right=n-1;int[] arr=new int[2];arr[0]=-1;arr[1]=-1;while(left<right){int mid=left+(right-left)/2;if(nums[mid]<target){left=mid+1;}else{right=mid;}}if(left==right&&nums[right]==target) arr[0]=left;left=0;right=n-1;while(left<right){int mid=left+(right-left+1)/2;if(nums[mid]<=target){left=mid;}else{right=mid-1;}}if(left==right&&nums[left]==target) arr[1]=left;return arr;}
}

3.寻找峰值 

 题目链接

https://leetcode.cn/problems/find-peak-element/description/

算法思路

寻找⼆段性:
任取⼀个点 i ,与下⼀个点 i + 1 ,会有如下两种情况:
  • arr[i] > arr[i + 1] :此时「左侧区域」⼀定会存在⼭峰(因为最左侧是负⽆穷),那么我们可以去左侧去寻找结果;
  • arr[i] < arr[i + 1] :此时「右侧区域」⼀定会存在⼭峰(因为最右侧是负⽆穷),那么我们可以去右侧去寻找结果。
当我们找到「⼆段性」的时候,就可以尝试⽤「⼆分查找」算法来解决问题。

代码呈现

class Solution {public int findPeakElement(int[] nums) {int n=nums.length;int left=0;int right=n-1;while(left<right){int mid=left+(right-left)/2;if(nums[mid]<nums[mid+1]){left=mid+1;}else{right=mid;}}return left;}
}

 ❤️😍😍😍😍😍😍😍😍😍😍😍😍😍😍😍😍😍

🍔我是小皮侠,谢谢大家都能看到这里!!

🦚主页已更新Java基础内容,数据结构基础,数据库,算法

🚕未来会更新Java项目,SpringBoot,Redis以及各种Java路线会用到的技术。

🎃求点赞!求收藏!求评论!求关注!

🤷‍♀️谢谢大家!!!!!!!!!

这篇关于【算法题】三道题理解算法思想——二分查找算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/863130

相关文章

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

C#实现查找并删除PDF中的空白页面

《C#实现查找并删除PDF中的空白页面》PDF文件中的空白页并不少见,因为它们有可能是作者有意留下的,也有可能是在处理文档时不小心添加的,下面我们来看看如何使用Spire.PDFfor.NET通过C#... 目录安装 Spire.PDF for .NETC# 查找并删除 PDF 文档中的空白页C# 添加与删

Springboot实现推荐系统的协同过滤算法

《Springboot实现推荐系统的协同过滤算法》协同过滤算法是一种在推荐系统中广泛使用的算法,用于预测用户对物品(如商品、电影、音乐等)的偏好,从而实现个性化推荐,下面给大家介绍Springboot... 目录前言基本原理 算法分类 计算方法应用场景 代码实现 前言协同过滤算法(Collaborativ

spring IOC的理解之原理和实现过程

《springIOC的理解之原理和实现过程》:本文主要介绍springIOC的理解之原理和实现过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、IoC 核心概念二、核心原理1. 容器架构2. 核心组件3. 工作流程三、关键实现机制1. Bean生命周期2.

深入理解Apache Kafka(分布式流处理平台)

《深入理解ApacheKafka(分布式流处理平台)》ApacheKafka作为现代分布式系统中的核心中间件,为构建高吞吐量、低延迟的数据管道提供了强大支持,本文将深入探讨Kafka的核心概念、架构... 目录引言一、Apache Kafka概述1.1 什么是Kafka?1.2 Kafka的核心概念二、Ka