【代码随想录】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开始的

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

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

目录
相关文章
|
6月前
【每日一题Day266】LC18四数之和 | 排序+双指针
【每日一题Day266】LC18四数之和 | 排序+双指针
41 1
|
6月前
|
存储
【每日一题Day294】LC88合并两个有序数组 | 双指针
【每日一题Day294】LC88合并两个有序数组 | 双指针
41 0
|
6月前
【每日一题Day260】LC15三数之和 | 排序 + 双指针
【每日一题Day260】LC15三数之和 | 排序 + 双指针
60 0
|
6月前
【每日一题Day261】LC16最接近的三数之和 | 双指针
【每日一题Day261】LC16最接近的三数之和 | 双指针
38 0
|
6月前
【每日一题Day306】LC228汇总区间 | 双指针
【每日一题Day306】LC228汇总区间 | 双指针
38 0
|
6月前
【每日一题Day249】LC1186删除一次得到子数组最大和 | 动态规划
【每日一题Day249】LC1186删除一次得到子数组最大和 | 动态规划
43 0
|
6月前
【每日一题Day259】LC167两数之和 II - 输入有序数组 | 双指针 二分查找
【每日一题Day259】LC167两数之和 II - 输入有序数组 | 双指针 二分查找
60 0
|
算法 C语言 C++
(C语言版)力扣(LeetCode)+牛客网(nowcoder)链表相关面试题OJ题解析(下)
现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。
(C语言版)力扣(LeetCode)+牛客网(nowcoder)链表相关面试题OJ题解析(上)
递归的写法看起来简洁,实际并没有迭代写法好理解,而且在空间复杂度上也比迭代高,这里的递归写法思路主要是先向下找到尾结点后,向上逐个返回,如果等于val值,就将该节点上一个元素直接指向该节点下一个元素,等于是将该点从链表中删除了
(C语言版)力扣(LeetCode)+牛客网(nowcoder)链表相关面试题OJ题解析(上)
|
容器
【代码随想录】LC 102. 二叉树的层序遍历
目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 三、知识风暴
49 0