不适用链表
顺口溜:总共5个移 一个都不能少
相交和相邻,start要+1
mid不能当益
查左end移 查右就start移 确定区间(通过开口来确定)while(內为手段)
输出变正常按序移 确定在上面这个区间你要区间的那个边界
(输出的时候如果是输出当前范围的左边界就从start)为你要求的
二分法的重点不在于指针移动 在于/2 循环目标在于分/缩小区间 不在于在循环中找到答案 最后找到的最小区间if判断
求any是target的元素 :普通做法
发生死循环+求first/last时无法保存已经找到的target
class Solution {
public int search(int[] arr, int target) {
if(arr==null||arr.length<=0){return -1;}
int start=0;
int end=arr.length-1;
int mid=0;
while(start<=end)
{
mid=start+(end-start)/2;
if(target==arr[mid])
{
return mid;
}
else if(target<arr[mid])
{
end=mid-1;
}
else if(target>arr[mid])
{
start=mid+1;
}
}
//if(arr[start]==target){return start;}
//if(arr[end]==target){return end;}
return -1;
}
}
防死循环+快速求any/first /last Index
class Solution {
public int search(int[] arr, int target) {
if(arr==null||arr.length<=0){return -1;}
int start=0;
int end=arr.length-1;
int mid=0;
while(start+1<end)
{
mid=start+(end-start)/2;
if(target==arr[mid])
{
end=mid;
}
else if(target<arr[mid])
{
end=mid;
}
else if(target>arr[mid])
{
start=mid;
}
}
if(arr[start]==target){return start;}
if(arr[end]==target){return end;}
return -1;}
}
题目让返回是第一个数你就先判断start while里面是你的处理方法 但最后的判断是最后剩的这两个区间你要取哪个根据是题目的问题
int start=0;
int end=arr.length-1;
int mid;
while(start+1<end)
{
mid=start+(end-start)/2;
if(target==arr[mid])
{
end=mid;//打印第一个重复的数字下标
//寻找第一次出现的位置,也就是说每次找到等于情况的时候,需要继续向左边找。
}
else if(target<arr[mid])
{
end=mid;
}
else if(target>arr[mid])
{
start=mid;
}
}
if(target==arr[start])//打印第一个 想从左边开始
{
return start;
}
if(target==arr[end])
{
return end;
}
左边界
打印重复的第一个下标
while循环里target==arr[mid] end=mid 让end不断靠左,当前是target他的前面还有重复的
输出的时候 左边界先判断start
打印重复的最后一个下标
while循环里target==arr[mid] start=mid 让start不断靠右
寻找最后一次出现的位置,也就是说每次找到等于情况的时候,需要继续向右边找。
输出的时候 右边界先判断end
给定一个排序数组和一个目标值,如果在数组中找到目标值则返回索引。如果没有,返回到它将会被按顺序插入的位置。
你可以假设在数组中无重复元素。
样例
[1,3,5,6],5 → 2
[1,3,5,6],2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6],0 → 0
挑战
时间复杂度为O(log(n))
- 先查找与target相等的左区间 右区间 找到直接返回
- 查找第一个大于等于target的元素 找比target大的左区间 然后index-1
- 查找最后一个小于target的位置 就是比target小的右区间 index+1
有可能找不到 因为当前的target为最大值那就插在末尾
因为是找比target小的所以是从右边开始 最后一个/