问题描述
给定一个 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]之间。
解题思路
20220113修改:
这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件。
这是一个很简单的问题,我们很容易就能想到用折半查找来找题目要求的target,但需要注意的是一些相关的细节,我们按照LeetCode上提供的函数输入变量来进行设计int search(int* nums, int numsSize, int target) {},即用指明数组首地址的指针和数组大小的numsSize来进行查找。
我选择的是递归的思想,因为递归的思想很清楚而且很容易写,且这道题对时间复杂度等没有要求,所以使用递归是无可厚非的。
使用递归时,要有一个最后判断退出的条件,由这个函数参数可得,当数组规模numsSize==0时,说明查找失败,则返回-1,代表查找未成功。
然后是划分的思想,
当nums[numsSize/2]==target时,说明查找成功,返回此时数组的下标numsSize/2;
当nums[numsSize/2]>target时,说明target在该数组左边的部分,则进入左边部分的数组继续查找search(nums, numsSize / 2 , target),此时数组首地址仍不变,但是数组规模变成了numsSize/2,表示原来数组从下标0到下标numsSize-1的元素数量;
当nums[numsSize/2]<target时,说明target在该数组右边的部分,则进入右边部分的数组继续查找search(nums + numsSize / 2 + 1, numsSize - numsSize / 2 - 1, target),此时数组首地址应调整为原数组下标为numsSize+1的位置,即nums+numsSize/2+1,而此时新数组的规模为原数组下标从numsSize/2+1到下标numsSize-1的元素数量,另外注意,当在该情况下未找到时,应返回-1,但若找到时,应返回初始数组的target下标,则此情况应返回numsSize / 2 + search(nums + numsSize / 2 + 1, numsSize - numsSize / 2 - 1, target) + 1;
此时整个函数已经写好了,但是提交时却有这样的错误
在最后加上一句return -1则可正确提交
以下为我写的代码
解题代码
int search(int* nums, int numsSize, int target) {
if (numsSize == 0) {
return -1;
}
if (nums[numsSize / 2] == target) {
return numsSize / 2;
}
else if (nums[numsSize / 2] > target) {
return search(nums, numsSize / 2 , target);
}
else if (nums[numsSize / 2] < target) {
if (search(nums + numsSize / 2 + 1, numsSize - numsSize / 2 - 1, target) == -1) {
return -1;
}
else {
return numsSize / 2 + search(nums + numsSize / 2 + 1, numsSize - numsSize / 2 - 1, target) + 1;
}
}
return -1;
}