LeetCode 75 —— 704. 二分查找

116 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情

LeetCode 75 —— 704. 二分查找

一、题目描述:

给定一个 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]之间。

来源:力扣(LeetCode) 链接:leetcode.cn/problems/bi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路分析:

  1. 这道题考察了什么思想?你的思路是什么?

    二分查找应该是最常用的算法之一,思路很简单,设置一个left和right,初始值left设置为0,right设置为数组长度减一。因为数组内元素是升序排列的,所以我们取数组中间元素的索引mid,然后将其指向的元素与目标值进行比较,如果该元素大于目标值,则将left的值设置为mid,如果该元素小于目标值,我们就将right的值设置为mid。直到mid指向的值等于目标值。

    func search(nums []int, target int) int {
        var left,right,mid int
        left = 0
        right = len(nums)-1
        mid = (right - left) / 2 + left 
    ​
        for nums[mid] != target{
            if((left + 1 == right || left == right) && (nums[left] != target && nums[right] != target) ){
                return -1
            }
            fmt.Println(left,right,mid) 
            if( nums[mid] < target ) {
                left = mid 
            }else { 
                right = mid
            }
            mid = (right - left) / 2.0 + left 
        }
    ​
        return mid
    }
    ​
    

    结果这种解法总是有部分测试用例过不去。

  2. 做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?

    不是一次通过,刚开始的第一想法是上面那种思路,但是有个问题,因为如果用nums[mid]与target进行判断,就会出现不知道什么时候退出的情况。因此不能使用上面那种思路。

    而应该是判断left是否大于right,因为当nums[mid] > target时,right = mid - 1,而

    nums[mid] < target时,left = mid + 1。因为mid = (right - left) / 2 + left,如果right比left大1,而直接给left或right赋值为mid的话,就会出现mid还是等于left,可能会导致原地踏步。

  3. 有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?

    写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。

    (版本二)左闭右开区间:

    func search(nums []int, target int) int {
        high := len(nums)
        low := 0
        for low < high {
            mid := low + (high-low)/2
            if nums[mid] == target {
                return mid
            } else if nums[mid] > target {
                high = mid
            } else {
                low = mid+1
            }
        }
        return -1
    }
    ​
    作者:carlsun-2
    链接:https://leetcode.cn/problems/binary-search/solution/704-er-fen-cha-zhao-er-fen-fa-zhong-xun-l74cr/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

三、AC 代码:

func search(nums []int, target int) int {
    var left,right,mid int
    left = 0
    right = len(nums)-1
    for left <= right {
        mid = (right - left) / 2 + left
        if(nums[mid] == target){
            return mid
        }else if(nums[mid] > target){
            right = mid - 1
        }else if nums[mid] < target{
            left = mid + 1
        }
    }
     
    return -1
}
​

四、总结:

二分查找的时间复杂度为O(log n),空间复杂度为O(1)。

下面上labuladong大佬的绝活:

image-20221009204325972

模板来源:

作者:掘金酱

链接:juejin.cn/post/706970…

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。