从小白开始刷算法 二分法篇 leetcode.704

简介: 从小白开始刷算法 二分法篇 leetcode.704

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


题目来源:力扣(LeetCode)


二分法


能否写出:能写出。

时间:20多分钟

思路:

初始化 start 为数组的起始索引(0), end 为数组的末尾索引(nums.length-1)。

  1. 进入循环,只要 start 不大于 end,就进行循环操作。
  2. 在每次循环中,计算中间元素的索引 middle,通过将 startend 的平均值赋给 middle。这样可以确保我们每次都在数组的中间位置进行查找。
  3. 检查中间元素 nums[middle] 是否等于目标值 target,如果是,则找到了目标值,返回 middle
  4. 如果中间元素 nums[middle] 大于目标值 target,说明目标值可能在中间元素的左侧,将 end 更新为 middle-1,缩小查找范围到左半部分。
  5. 如果中间元素 nums[middle] 小于目标值 target,说明目标值可能在中间元素的右侧,将 start 更新为 middle+1,缩小查找范围到右半部分。
  6. 继续下一次循环,直到 start 大于 end,此时查找范围为空,循环结束。
  7. 如果循环结束仍未找到目标值,则返回 -1,表示目标值不存在于数组中。

在代码中,start + (end - start) / 2 的目的是为了计算中间元素的索引 middle。这样的计算方式是为了避免整数溢出的问题,并确保得到正确的中间索引值。

start + (end - start) / 2 等价于 (start + end) / 2,它们都可以用来计算中间索引。然而,使用 (start + end) / 2 的方式可能会导致整数溢出的问题,特别是当 startend 很大时。通过使用 (end - start) / 2 可以避免这个问题,因为这样计算的差值一定是非负的。

例如,假设 start = 10000end = 20000,使用 (start + end) / 2 的方式计算中间索引会得到 15000,这是正确的。但是,如果 startend 很大,例如 start = 2^31 - 1end = 2^31 - 1,计算中间索引时使用 (start + end) / 2 就会导致整数溢出,得到错误的结果。

因此,使用 (end - start) / 2 可以确保计算中间索引时避免整数溢。

b站 up 爱学习的饲养员 陈述了这个问题,我这边举了个例子扩展。


// 仅是我的思路代码,leetcode上大神更厉害
class Solution {
    public int search(int[] nums, int target) {
        int end = nums.length-1;
        int start = 0;
        while (start<=end){
          //计算中间元素的索引
            int middle= start+(end-start)/2;
            //找到目标值,返回
            if(nums[middle]==target){
                return middle;
            }
            //目标值可能在中间元素的左侧
            if(nums[middle]>target){
            //将 end 更新为 middle-1,缩小查找范围到左半部分
                end = middle-1;
            }else {
            //目标值可能在中间元素的右侧
                start = middle+1;
            }
        }
        return -1;
    }
}

时间复杂度: O(log n)

空间复杂度:O(1)

相关文章
|
1天前
|
存储 算法 JavaScript
怎么刷算法,leetcode上有哪些经典题目
怎么刷算法,leetcode上有哪些经典题目
18 0
|
1天前
|
算法 Java
[Java·算法·中等] LeetCode15. 三数之和
[Java·算法·中等] LeetCode15. 三数之和
35 0
|
1天前
|
存储 算法
Leetcode 30天高效刷数据结构和算法 Day1 两数之和 —— 无序数组
给定一个无序整数数组和目标值,找出数组中和为目标值的两个数的下标。要求不重复且可按任意顺序返回。示例:输入nums = [2,7,11,15], target = 9,输出[0,1]。暴力解法时间复杂度O(n²),优化解法利用哈希表实现,时间复杂度O(n)。
21 0
|
1天前
|
算法
代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形
代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形
23 3
|
1天前
|
存储 算法
代码随想录算法训练营第五十九天 | LeetCode 739. 每日温度、496. 下一个更大元素 I
代码随想录算法训练营第五十九天 | LeetCode 739. 每日温度、496. 下一个更大元素 I
22 1
|
1天前
|
算法
代码随想录算法训练营第五十七天 | LeetCode 739. 每日温度、496. 下一个更大元素 I
代码随想录算法训练营第五十七天 | LeetCode 739. 每日温度、496. 下一个更大元素 I
18 3
|
1天前
|
算法
代码随想录算法训练营第五十六天 | LeetCode 647. 回文子串、516. 最长回文子序列、动态规划总结
代码随想录算法训练营第五十六天 | LeetCode 647. 回文子串、516. 最长回文子序列、动态规划总结
34 1
|
1天前
|
算法
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
24 1
|
1天前
|
算法 API DataX
二叉树(下)+Leetcode每日一题——“数据结构与算法”“对称二叉树”“另一棵树的子树”“二叉树的前中后序遍历”
二叉树(下)+Leetcode每日一题——“数据结构与算法”“对称二叉树”“另一棵树的子树”“二叉树的前中后序遍历”
|
1天前
|
算法 DataX
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”