欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 算法专题——二分查找

算法专题——二分查找

2025/1/19 2:28:53 来源:https://blog.csdn.net/weixin_59371851/article/details/145011870  浏览:    关键词:算法专题——二分查找

目录

前言

1、二分查找

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

3、搜索插入位置

 4、 x 的平⽅根

5、山峰数组的峰顶 

 6、寻找峰值


前言

本文主要介绍二分算法的思想和相关题目。很多介绍都说二分算法往往需要有序,但实际有序并不是使用二分算法的核心,使用二分算法的核心应该是两段性,也就是能根据题目条件把整个区间分为两段。


1、二分查找

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

 本题是最基础的二分查找算法,之后的题目都是建立在本题的基础上:

a. 定义 left , right 指针,分别指向数组的左右区间。
b. 找到待查找区间的中间点 mid ,找到之后分三种情况讨论:

  • i. arr[mid] == target 说明正好找到,返回 mid 的值;
  • ii. arr[mid] > target 说明 [mid, right] 这段区间都是⼤于 target 的,因此舍去右边区间,在左边 [left, mid -1] 的区间继续查找,即让 right = mid -1 ,然后重复 2 过程;
  • iii. arr[mid] < target 说明 [left, mid] 这段区间的值都是⼩于 target 的,因此舍去左边区间,在右边 [mid + 1, right] 区间继续查找,即让 left = mid +1 ,然后重复 2 过程;

c. 当 left 与 right 错开时,说明整个区间都没有这个数,返回 -1 。

class Solution {public int search(int[] nums, int target) {int left=0,right=nums.length-1;while(left<=right){int mid=left+(right-left)/2;//防止溢出if(nums[mid]==target){return mid;}else if(nums[mid]<target){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/

二分查找总共有三种方式,分别是最基本的查找方法,查找右边一段的左边界和查找左边一段的右边界。基本二分查找用的很少,比如本题如果使用基本查找方法找到之后再左右遍历在特殊情况下时间复杂度会退化到O(n)。左右边界查找方法代码如下:

class Solution {public int[] searchRange(int[] nums, int target) {int[] ret=new int[2];ret[0]=-1;ret[1]=-1;if(nums.length==0){return ret;}//找左端点int left=0,right=nums.length-1;while(left<right){int mid=left+(right-left)/2;if(nums[mid]>=target){right=mid;}else{left=mid+1;}}if(nums[left]==target){ret[0]=left;}else {return ret;}//找右端点left=0;right=nums.length-1;while(left<right){int mid=left+(right-left+1)/2;if(nums[mid]<=target){left=mid;}else{right=mid-1;}}if(nums[right]==target){ret[1]=right;}else {return ret;}return ret;}
}

3、搜索插入位置

链接:https://leetcode.cn/problems/search-insert-position/description/ 

本题可以将区间分为两部分,左区间小于等于目标值,右区间大于目标值,然后根据寻找右端点的写法就可以解题。(实际分为左区间小于右区间大于等于找左端点会更好一些,一般要返回的值在哪个区间内就把等号加到那个区间里)。

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

 4、 x 的平⽅根

链接:https://leetcode.cn/problems/sqrtx/description/

 本题和上一题类似,可以将区间分为两部分,左区间小于等于目标值,右区间大于目标值,然后根据寻找右端点的写法就可以解题。

class Solution {public int mySqrt(int x) {long left=0,right=x;while(left<right){long mid=left+(right-left+1)/2;if(mid*mid<=x){left=mid;}else{right=mid-1;}}return (int)left;}
}

5、山峰数组的峰顶 

链接:https://leetcode.cn/problems/peak-index-in-a-mountain-array/submissions/592155701/

本题可以根据题目要求把数组分为两段,第一段满足每个元素大于前一个元素,第二段满足每个元素小于前一个元素,使用二分查找。

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

 6、寻找峰值

链接:https://leetcode.cn/problems/find-peak-element/

如果满足当前值大于前一个值,那么当前点的右边一定存在峰值,如果满足当前值小于前一个值,那么 当前点的左边一定存在峰值,只要能将区间分割成两部分并利用条件逐渐排除其中的一部分,那么就可以使用二分查找。

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com