1、leetcode704 二分查找*

本文详细解析了LeetCode 704题目——二分查找的两种实现方法,介绍了如何通过二分法在有序数组中查找特定元素,并提供了具体的Java代码示例。

leetcode 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

二分法:方法一

这道题是二分查找里面最简单的一道题,我们可以从简单入手,看while循环里的条件到底怎么写,到底要不要=,以及right=mid还是right=mid-1等等。
建议方法一和方法二对照着看。

public int search(int[] nums, int target) {
        int left=0;
        int right=nums.length;//二分查找索引范围[left,right)
	
	   //这边条件很重要,当left==right时,退出循环;为什么不写<=?
	   //因为上面的索引范围是在[left,right),right是不包括的,如果<=,
	   //那么left==right是满足循环条件的,但是下面nums[mid]必定会数组
	   //角标越界,所以这边循环条件只能写<。
        while(left<right){  
            int mid=(left+right)>>1;
            if(nums[mid]==target){
                return mid;
            }else if(nums[mid]>target){
            //因为nums[mid]>target,right=mid;有人要问right=mid-1
            //行不行,不可以,因为mid-1很可能就是答案,上面的索引范围是
            //[left,right),right是不包括的,所以这边只能是right=mid。
            //写成right=mid-1,就相当于索引范围是[left,right],
            //左右都包括了,和一开始的条件不一致。
                right=mid;
            }else{
                left=mid+1;
            }
        }
        //即left==right,退出循环;right索引是不包括的,
        //left==right说明没有查找到,返回-1;
        return -1;
    }

二分法:方法二

public int search(int[] nums, int target) {
        int left=0;
        //和方法一的不同处,索引范围是[left,right]
        int right=nums.length-1;
        
        //这边退出循环的条件是left>right;通俗点讲就是left==right是程序的最后一次循环。
        //方法一不是这样的。方法一是当left==right就会退出循环。
        //为什么会这样?是因为初始化索引范围不同造成的。
        while(left<=right){
            int mid=(left+right)>>1;
            if(nums[mid]==target){
                return mid;
            }else if(nums[mid]>target){
            //因为nums[mid]>target,所以right=mid-1,注意这边不是
            //right=mid,因为nums[mid]已经不符合条件了,为了和初始化
            //索引范围一致,即[left,right],这边需要写成right=mid-1,
            //因为mid-1很可能就是答案,但是mid绝不可能是答案。
                right=mid-1;
            }else{
            //left和上面的right同理
                left=mid+1;
            }
        }
        //当left>right,退出循环
        return -1;
    }
Leetcode 704题是二分查找的典型题目。二分查找借助数组有序的特点,进行折半查找。 从解题思路来看,由于数组有序,所以可以通过不断缩小查找范围来找到目标值。具体做法是设置 `low = 0`,`heigh = 数组长度 - 1`,`mid = (low + heigh) / 2`。当 `nums[mid] = target` 时,返回 `mid`;当 `nums[mid] < target` 时,所要查找的值在 `mid` 的右边,更新 `low = mid + 1`;当 `nums[mid] > target` 时,所要查找的值在 `mid` 的左边,更新 `heigh = mid - 1`。代码实现如下: ```c int search(int* nums, int numsSize, int target){ int low = 0; int heigh = numsSize - 1; int mid; while(heigh >= low){ mid = (low + heigh) / 2; if(nums[mid] == target){ return mid; } if(nums[mid] < target){ low = mid + 1; } else { heigh = mid - 1; } } return -1; } ``` 从二分查找的整体过程分析,首先要设定左右指针,找出中间位置,并判断该位置值是否等于 `target`。若 `nums[mid] == target` 则返回该位置下标;若 `nums[mid] > target` 则右侧指针移到中间;若 `nums[mid] < target` 则左侧指针移到中间。其时间复杂度为 $O(logN)$ [^2][^3]。 不过二分查找涉及很多边界条件,逻辑虽然简单,但容易出错。例如到底是 `while(left < right)` 还是 `while(left <= right)`,到底是 `right = middle` 还是 `right = middle - 1`,这都需要根据区间的定义来确定 [^5]。 此外,还有不朴素二分查找,即二分查找的循环里左右指针的行为为 `left = mid + 1,right = mid` 或者 `left = mid,right = mid - 1` 这两种情况,需要专门的模板来解决边界处理问题 [^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值