[leetcode刷题】(二)704. 二分查找

一、数组介绍

数组是存放在连续内存空间上的相同类型数据的集合。
• 数组下标都是从0开始的。
• 数组内存空间的地址是连续的

一维数组
图源代码随想录
二维数组
图源代码随想录
在C++中二维数组在地址空间上是连续的

二、二分算法介绍

给定一个排序数组nums和一个目标值target,在数组中找到目标值,并返回其索引(下标)。如果目标值不存在于数组中,就返回-1。

搞定二分法主要是要解决两个问题:

  • left、right值的初始值及其变化情况

  • left、right与target值的大小关系(≥ > < ≤ )

在解决这两个问题前,我们需要先知道集给定数组的取值区间的开闭情况:
(1)左闭右闭
(2)左闭右开
PS:不会出现左开右闭的情况

(1)左闭右闭
当数组区间为左闭右闭时,left、right的两个注意点的情况是:

  • left、right的初始值分别是:left = 0,right = num.szie - 1
  • while语句的条件表达式是left ≤ right;而 if 判定后的right和left的变化情况是:right = middle - 1,left = middle + 1
    我们可以举例子来理解,假定数组是[1,1],那么left与right是可能存在相等的情况的,这样的话,我们在while的条件表达式,也应该考虑到right和left相等的情况,所以此时的条件表达式应该为 left ≤ right;
    同样的,因为右边值是可以取到的(闭区间),所以right的初始值要从数组长度-1开始;
    而当nums[middle]大于target时:
    在这里插入图片描述
    那么此时我们要更新right,而因为我们已经拿nums[middle]的值和target比较过了,且没有找到target对应下标,所以为了更好的处理数组的区间值,我们需要去掉比较过的middle对应值,而又因为是闭区间,所以我们需要让right = middle - 1;同样的理解,left = middle + 1
    此时的伪代码如下:
left = 0
right = num.szie - 1 
while (left ≤ right) {
	middle = (left + right) / 2
// 为了防止溢出,middle = (left + right) / 2可以改为left + (right - left) / 2
	if (nums[target] > target)
		right = middle - 1;
	else if (nums[target] < target)
		left = middle + 1;
	else return middle;
}
return -1;

(2)左闭右开
当数组区间为左闭右开时,left、right的两个注意点的情况是:

  • left、right的初始值分别是:left = 0,right = num.szie
  • while语句的条件表达式是left < right;而 if 判定后的right和left的变化情况是:right = middle ,left = middle
    同样的,我们也可以举例子说理解,假定数组是[1,1), 这个时候left = right,但1怎么会小于1呢?也就是left是不能等于right的,所以while语句的条件表达式是:left < right;
    同样的,因为数组右边是开区间,如果我们将right的初始值从num.szie - 1开始的话,那么数组最右边值就无法取到,所以right的初始值为num.szie;
    同样的,当nums[middle]大于target时:
    在这里插入图片描述
    我们也将nums[middle]的值和target比较过了,并且没有找到target对应下标,但是因为数组的右边是开区间,我们只用令right = middle就好,这样就不会取到已经比较过的middle值了;同样的,left的取值为:left = middle
    此时的伪代码如下:
left = 0
right = num.szie 
while (left < right) {
	middle = (left + right) / 2
// 为了防止溢出,middle = (left + right) / 2可以改为left + (right - left) / 2
	if (nums[target] > target)
		right = middle;
	else if (nums[target] < target)
		left = middle;
	else return middle;
}
return -1;

三、704 二分查找

力扣题目链接
将伪代码整理成C++代码即可,以下是我的运行代码

class Solution{
public:
    int search (vector<int>& nums, int target){
       int left = 0;
       int right = nums.size() -1;
       while (left <= right) {
           int middle = left + ((right - left) / 2);
           if (nums[middle] < target)
                left = middle + 1;
           else if (nums[middle] > target)
                right = middle - 1;
           else return middle;
        }
        return -1;
    }
};

四、参考链接

1、视频链接:【手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找】

2、文章链接:代码随想录 | 704. 二分查找

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值