目录
基本概念
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
二分搜索的核心是每次搜索“丢弃”一半的数据
模式识别:有序或者部分有序,基本使用二分搜索及其变种
力扣题
33. 搜索旋转排序数组
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组
[0,1,2,4,5,6,7]
可能变为[4,5,6,7,0,1,2]
)。搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回
-1
。你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
示例 1:
输入: nums = [4,5,6,7,0,1,2]
, target = 0 输出: 4示例 2:
输入: nums = [4,5,6,7,0,1,2]
, target = 3 输出: -1
暴力解法,线性搜索数组,而搜索整个数组的时间复杂度为O(n),这是该题时间复杂度的上界
算法复杂度必须是O(logn),这提示可以使用二分搜索方法
将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。循环
若中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的,我们只要在有序的半段里用首尾两个数组来判断目标值是否在这一区域内,以此确定保留哪半边
class Solution {
public int search(int[] nums, int target) {
int left=0,right=nums.length-1,mid=0;
while(left<=right){
mid=left+(right-left)/2;//调整中心点
if(nums[mid]==target) return mid;
if(nums[mid]>=nums[left]){//说明左段是顺序
if(target>=nums[left]&&target<nums[mid]){//目标在左段
right=mid-1;
}else{
left=mid+1;
}
}else{//右段是顺序
if(target>nums[mid]&&target<=nums[right]){//目标在右段
left=mid+1;
}else{
right=mid-1;
}
}
}
return -1;
}
}