二分搜索
参考内容:https://greyireland.gitbook.io/algorithm-pattern/ji-chu-suan-fa-pian/binary_search
给一个有序数组和目标值,找第一次/最后一次/任何一次出现的索引,如果没有出现返回-1
模板四点要素
- 初始化:
start=0、end=len-1
- 循环退出条件:
start + 1 < end
- 比较中点和目标值:
A[mid] ==、 <、> target
- 判断最后两个元素是否符合:
A[start]、A[end] ? target
时间复杂度 O(logn)
,使用场景一般是有序数组的查找
模板:
不论是模板几,基础的思想都是利用判断左右指针与目标值之间的关系不断缩小左右指针包含的范围,最终得出一个确定的值或者确定的区间。
本文大部分将用3,因为可以返回两个指针,将取舍交给while循环结束后进行。当然,简单情况唯一解时用1方便。
示例
二分查找
给定一个 n 个元素有序的(升序)整型数组 nums
和一个目标值 target ,写一个函数搜索 nums
中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
提示:
你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。
class Solution {
public int search(int[] nums, int target) {
int n=nums.length;
int left=0,right=n-1;
while(left<=right){
int mid=left+(right-left)/2;
if(target==nums[mid]){
return mid;
}else if(nums[mid]<target){
left=mid+1;
}else{
right=mid-1;
}
}
return -1;
}
}
常见题目
1、搜索区间
描述
给定一个包含 n
个整数的排序数组,找出给定目标值 target
的起始和结束位置。
如果目标值不在数组中,则返回[-1, -1]
样例 1:
输入:
数组 = []
target = 9
输出:
[-1,-1]
解释:
9不在数组中。
样例 2:
输入:
数组 = [5, 7, 7, 8, 8, 10]
target = 8
输出:
[3,4]
解释:
数组的[3,4]子区间值为8。
挑战
时间复杂度 O(log n)
思路
因为是寻找区间,所以要分左右边界进行两次寻找。开始前要注意对数组的判空。
这里使用的是模板三。
public class Solution {
/**
* @param A: an integer sorted array
* @param target: an integer to be inserted
* @return: a list of length 2, [index1, index2]
*/
public int[] searchRange(int[] A, int target) {
// write your code here
int n=A.length;
int left=0,right=n-1;
int[] res=new int[2];
res[0]=-1;
res[1]=-1;
if(n==0){
return res;
}
while(left+1<right){
int mid=left+(right-left)/2;
if(A[mid]<target){
left=mid;
}else{
right=mid;
}
}
res[0]=A[left]==target?left:(A[right]==target?right:-1);
left=0;
right=n-1;
while(left+1<right){
int mid=left+(right-left)/2;
if(A[mid]>target){
right=mid;
}