题目
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
解题思路
针对这个题目,想要实现其实很容易,我首先想到的是遍历数组求解,但题目标题既然是二分查找,而且又是一个有序数组,那么我们不妨设数组中的元素都是不重复的,我们就可以采用二分查找的思想来求解。
Tips:有重复元素的情况下使用二分查找法返回的元素下标可能不是唯一的
想着简单,在我自己尝试写了之后,数据反反复复与答案不一致...
int search(int* nums, int numsSize, int target)
{
int left = 0;
int right = numsSize ;
int mid;
while (left < right)
{
mid = (left + right) / 2;
if (target < nums[mid])
{
right = mid ;
}
else if (target > nums[mid])
{
left = mid;
}
else
{
return mid;
}
}
return -1;
}
在自己找不出错误后,查阅了官网的一些解题思路,发现问题就出在边界判断上
二分查找难点就在于区间的处理上,我们将其大致分为左闭右闭[a,b]区间、左闭右开[a,b)区间(左开右闭(a,b]同理)
左闭右闭[a,b]
首先附上我自己写的左闭右闭代码:
//左闭右闭的二分查找
int search(int* nums, int numsSize, int target)
{
int left = 0;
int right = numsSize - 1;
int mid;
while (left <= right)
{
mid = (left + right) / 2;
if (target < nums[mid])
{
right = mid - 1;
}
else if (target > nums[mid])
{
left = mid + 1;
}
else
{
return mid;
}
}
return -1;
}
①首先是right值,因为是右闭区间,右边能取到,我们要取到边界值即numsSize-1
②其次是while(left <= right),我们要不要这个等号,因为是一个[a,b]区间,那么我们取相同左右即[1,1]也是个合法值,因此要加上=号
③在target < nus[mid]上因为是左右闭的区间,右终点要取到有可能性的值,而nums[mid]已经被我们排除了,故直接mid - 1,同理可得left = mid + 1
左闭右开[a,b)
先附上代码:
//左闭右开的二分查找
int search(int* nums, int numsSize, int target)
{
int left = 0;
int right = numsSize ;
int mid;
while (left < right)
{
mid = (left + right) / 2;
if (target < nums[mid])
{
right = mid;
}
else if (target > nums[mid])
{
left = mid + 1;
}
else
{
return mid;
}
}
return -1;
}
①right值,因为是右开区间,右边不能取到,我们直接取numsSize
②while(left < right),因为是一个[a,b)区间,那么我们取相同左右即[1,1)是个非法值,不能加上=号
③在target < nus[mid]上因为是右开的区间,右终点是取不到边界值的,故直接right = mid
④在target > nus[mid]因为变的是左终点,左是闭的,所以和之前一样要left = mid + 1
最后的话
只是一个入门菜鸟的做题笔记,如有误恳请指正!