【代码随想录】LC 704. 二分查找

简介: 防止溢出可以将int mid = (left + right) / 2;改为 int mid = left + ((right - left) / 2);或int mid = left + ((right - left) >> 1);。数组理论基础数组下标都是从0开始的数组在内存空间的地址是连续的数组中的元素只能覆盖,不能删除。

一、题目

1、原题链接

704. 二分查找


2、题目描述

b161e16bb32888c7bc18adbc0802a024_b74e9426f2ce4ed18a238f20cfdbe429.png


二、解题报告

1、思路分析

二分查找有一般有两种写法,主要思想是利用搜索区间的定义来确定代码条件:


[left,right](左闭右闭)

如果将区间定义为左闭右闭,则意味着left和right的值都可以取到,而且left和right的值可以相等。所以:

初始left=0、right=nums.size()-1。

循环条件需要设置为left<=right

当nums[mid]>target时,更新right=mid-1。(因为根据区间定义,此时如果使right=mid,区间可以取到mid,而已知mid不满足条件,故应将区间缩小为[left,mid-1])

当nums[mid]<target时,更新为left=mid+1。(因为根据区间定义,此时如果使left=mid,区间可以取到mid,而已知mid不满足条件,故应将区间缩小为[mid+1,right])

当nums[mid]==target时,返回mid。

否则,返回-1。

[left,right)(左闭右开)

如果将区间定义为左闭右开,则意味着left的值可以取到,而right的值取不到,而且left和right的值不可以相等。所以:

初始left=0、right=nums.size()。

循环条件需要设置为left<right

当nums[mid]>target时,更新right=mid。(因为根据区间定义,此时如果使right=mid-1,区间取不到mid-1,会使搜索区间丢失mid-1,故应将区间缩小为[left,mid))

当nums[mid]<target时,更新left=mid+1。(因为根据区间定义,此时如果使left=mid,区间可以取到mid,而已知mid不满足条件,故应将区间缩小为[mid+1,right))

当nums[mid]==target时,返回mid。

否则,返回-1。

2、时间复杂度

二分查找时间复杂度为O (log n)


3、代码详解

左闭右闭区间定义代码


class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            //防止溢出可以改为:
            //int mid = left + ((right - left) / 2);
            //或
            //int mid = left + ((right - left) >> 1);
            int mid = (left + right) / 2;
            if (nums[mid] > target) right = mid - 1;
            else if (nums[mid] < target) left = mid + 1;
            else return mid;
        }
        return -1;
    }
};


左闭右开区间定义代码


class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size();
        while (left < right) {
            //防止溢出可以改为:
            //int mid = left + ((right - left) / 2);
            //或
            //int mid = left + ((right - left) >> 1);
            int mid = (left + right) / 2;
            if (nums[mid] > target) right = mid;
            else if (nums[mid] < target) left = mid + 1;
            else return mid;
        }
        return -1;
    }
};


三、知识风暴

注意mid是下标不是值,与target比较时是用nums[mid]。

防止溢出可以将int mid = (left + right) / 2;改为 int mid = left + ((right - left) / 2);或int mid = left + ((right - left) >> 1);。

数组理论基础

数组下标都是从0开始的

数组在内存空间的地址是连续的

数组中的元素只能覆盖,不能删除。

目录
相关文章
|
3月前
【每日一题Day266】LC18四数之和 | 排序+双指针
【每日一题Day266】LC18四数之和 | 排序+双指针
29 1
|
3月前
【每日一题Day331】LC2560打家劫舍 IV | 二分查找 + 贪心
【每日一题Day331】LC2560打家劫舍 IV | 二分查找 + 贪心
28 0
|
3月前
【每日一题Day149】LC2389和有限的最长子序列 | 贪心+前缀和+二分查找
【每日一题Day149】LC2389和有限的最长子序列 | 贪心+前缀和+二分查找
32 0
|
3月前
|
存储
【每日一题Day294】LC88合并两个有序数组 | 双指针
【每日一题Day294】LC88合并两个有序数组 | 双指针
23 0
|
3月前
【每日一题Day249】LC1186删除一次得到子数组最大和 | 动态规划
【每日一题Day249】LC1186删除一次得到子数组最大和 | 动态规划
35 0
|
3月前
【每日一题Day306】LC228汇总区间 | 双指针
【每日一题Day306】LC228汇总区间 | 双指针
29 0
|
3月前
【每日一题Day260】LC15三数之和 | 排序 + 双指针
【每日一题Day260】LC15三数之和 | 排序 + 双指针
50 0
|
3月前
【每日一题Day286】LC21合并两个有序链表 | 链表模拟 递归
【每日一题Day286】LC21合并两个有序链表 | 链表模拟 递归
27 0
|
3月前
【每日一题Day261】LC16最接近的三数之和 | 双指针
【每日一题Day261】LC16最接近的三数之和 | 双指针
29 0
|
3月前
【每日一题Day288】LC344反转字符串 | 双指针 位运算
【每日一题Day288】LC344反转字符串 | 双指针 位运算
17 0