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

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

相关文章

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

hdu1496(用hash思想统计数目)

作为一个刚学hash的孩子,感觉这道题目很不错,灵活的运用的数组的下标。 解题步骤:如果用常规方法解,那么时间复杂度为O(n^4),肯定会超时,然后参考了网上的解题方法,将等式分成两个部分,a*x1^2+b*x2^2和c*x3^2+d*x4^2, 各自作为数组的下标,如果两部分相加为0,则满足等式; 代码如下: #include<iostream>#include<algorithm

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个