1.题目描述
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
2.输入
输入数组nums 和要找的数字target
3.输出
若数组中存在target,则输出其下标,若数组中不存在target则输出-1
4.输入样例1
样例 1 Copy
nums= [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
5.输入样例2
样例 2 Copy
输入: nums= [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums中因此返回 -1
6.算法思路
算法思路
二分思想:
根据数据的性质,经过某次判断,可以将数据一分为二,舍去其中一半的数据,而在剩下的数据中查找。
在这道题目里面,我们可以先判断中间元素 arr[ret],由于 arr[ret] 左边的元素都是严格小于 arr[ret] 的, arr[ret] 右边的元素都是严格大于 arr[ret]。根据中间元素与目标值 target 的大小关系,可以分为以下三种情况:
arr[ret] == target 说明正好找到,返回 mid 的值;
arr[ret] > target 说明 [end, right] 这段区间都是大于 target 的,因此舍去右边区间,在左边 [left, ret -1] 的区间继续查找;
arr[ret] < target 说明 [open, mid] 这段区间的值都是小于 target 的,因此舍去左边区间,在右边 [ret + 1, end] 区间继续查找;
由此,我们就能在做一次判断的时候,干掉一半的数据,从而提高我们的查找效率。
7.算法优化思想
当我们再求两个数的平均数的时候,如果直接用 (open + end) / 2 的方式的话,可能会造成加法的运算超过 int 的最大值,从而发生数据溢出的情况。
因此我们改用 ret = open + (end - open) / 2 的形式(大家可以手动把这个算式通分,就会得到上述写法)。因为 open 和 end 都是整形,两者相间绝对不会超出 int 的最大范围。
8. 题解
- int search(int* nums, int numsSize, int target)
{
int end=numsSize-1,open=0,ret=(end+open)/2;
while(open<=end)
{
if(nums[ret]>target)
{
end=ret-1;
ret=(end+open)/2;
}
else if(nums[ret]<target)
{
open=ret+1;
ret=(end+open)/2;
}
else if(nums[ret]==target)
return ret;
}
return -1;
}