小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
题目
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
提示:
- 你可以假设
nums中的所有元素是不重复的。 n将在[1, 10000]之间。nums的每个元素都将在[-9999, 9999]之间。
解题思路
- 先判断数组是否为空,为空直接返回
-1,不为空继续 - 定义变量
left表示左边下标、middle表示中间下标、right表示右边下标、num中间下标的值nums[middle] - 查找范围始终是
[left,right],当left > right就不需要继续查找了,说明不存在,初始范围是[0,len(nums)-1] - 当
target = num返回middle - 当
target > num说明 查询范围在[middle+1, right] - 当
target < num说明 查询范围在[left, middle-1] - 假如始终没有找到说明不存在
代码
func main() {
nums := []int{-1, 0, 3, 5, 9, 12}
target := 4
fmt.Println("nums = [-1,0,3,5,9,12], target = " + strconv.Itoa(target) + ", 下标为: " + strconv.Itoa(search(nums, target)))
target = 9
fmt.Println("nums = [-1,0,3,5,9,12], target = " + strconv.Itoa(target) + ", 下标为: " + strconv.Itoa(search(nums, target)))
}
func search(nums []int, target int) int {
if nil == nums {
return -1
}
var left, middle, right, num int
left = 0
right = len(nums) - 1
for left <= right {
middle = (right-left)/2 + left
num = nums[middle]
fmt.Println("left=" + strconv.Itoa(left) + "," +
"middle=" + strconv.Itoa(middle) + "," +
"right=" + strconv.Itoa(right) + "," +
"num=" + strconv.Itoa(num))
if num == target {
return middle
} else if target > num {
left = middle + 1
} else {
right = middle - 1
}
}
return -1
}
打印结果
left=0,middle=2,right=5,num=3
left=3,middle=4,right=5,num=9
left=3,middle=3,right=3,num=5
nums = [-1,0,3,5,9,12], target = 4, 下标为: -1
left=0,middle=2,right=5,num=3
left=3,middle=4,right=5,num=9
nums = [-1,0,3,5,9,12], target = 9, 下标为: 4
复杂度分析
- 时间复杂度:
O(log n),其中n是数组的长度。 - 空间复杂度:
O(1)。