LeetCode-算法入门-704.二分查找

113 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目

给定一个 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

提示:

  1. 你可以假设 nums 中的所有元素是不重复的。
  2. n 将在 [1, 10000]之间。
  3. 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)