算法训练营 | 二分查找专项

简介: 算法训练营 | 二分查找专项

一、前言

每天都有刷算法但是确实缺少一个陪跑,借着这次卡哥的训练营来整体的完成一次算法学习和一刷,说起来也挺惭愧的,进卡哥的知识星球也半年多了,还没说过话。。

网络异常,图片无法展示
|

闲话少说, 今天是算法训练营的第一天,目标是【数组】模块 LeetCode的 704,二分查找和 27. 移除元素

二、LeetCode 704. 二分查找

题目描述

网络异常,图片无法展示
|

解题思路

  • 首先题中有说这是一个有序且升序的数组,那么肯定是二分法了
  • 直接设置一个左右下标 left和 right,把控好有左右边界来遍历获取中间值就可以了
  • 这里需要注意的是左右边界的判定
  • 同时,因为是有序的,所以当数组最小值 nums[0]都小于 target或者数组最大值 nums[nums.length - 1] 大于 target那么证明这个数组中不可能存在 target

代码展示

public int search(int[] nums, int target) {
    // 因为 nums是有序的, 那最小的如果大于 target或者最大的小于 target,则代表数组中不可能存在大小 target的元素
    if (nums[0] > target || nums[nums.length - 1] < target){
        return -1;
    }
    int left = 0, right = nums.length - 1;
    // 因为是二分法,所以当左右双指针相等的时候代表数组遍历完成
    while(left <= right){
        // 获取当前左右边界的中间下标
        int temp = left + (right - left) / 2;
        if (nums[temp] > target){
            // 如果中间的树都大于 target,那么右边界向左移动
            right = temp - 1;
        }else if (nums[temp] < target){
            // 如果中甲的树小于 target, 那么左边界移动
            left = temp + 1;
        }else{
            return temp;
        }
    }
    return -1;
}
复制代码

提交结果

网络异常,图片无法展示
|

总结

不得不说,很多东西不去练习真的会忘记,万万没想到这道题在之前我刷过四遍,虽然这次重做本题有些游刃有余,但是在细节处理上还是有一些小瑕疵,后续代码通过看代码随想录进行了相应的改进

网络异常,图片无法展示
|

LeetCode 27. 移除元素

题目描述

网络异常,图片无法展示
|

思路分析

  • 首先这道题需要注意的是既要修改数组,还要记录数组中元素值非 val的个数

这道题我们还是可以使用双指针来做, 一个指针去遍历数组, 另外一个指针去修改数组的同时记录长度,具体可看代码展示

代码展示

public int removeElement(int[] nums, int val) {
    // left一直向前走, right记录长度
    int left = 0, right = 0;
    for (; left < nums.length; left++) {
        // 如果当前元素为 val则 left继续向前走
        if (nums[left] != val){
            // 如果当前元素不为 val则修改,right++
            nums[right++] = nums[left];
        }
    }
    return right;
}
复制代码

提交结果

网络异常,图片无法展示
|

补充

在【代码随想录】网站中,本题还给了另外一种解法,相向双指针法,但是相对来讲更繁琐且不易理解, 具体如下

网络异常,图片无法展示
|

LeetCode  34. 在排序数组中查找元素的第一个和最后一个位置

题目描述

网络异常,图片无法展示
|

思路分析

  • 老规矩,认真审题
  • 这道题题目写的是非递减数组
  • 目标值的开始结束位置
  • 时间复杂度为 0(log n)

三种情况:

  • 不存在
  • 存在两个 val
  • 只有一个 val

依旧是双指针来做,不过这次是用两个双指针

代码展示

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        // 因为是二分法,所以当左右双指针相等的时候代表数组遍历完成
        while(left <= right){
            // 获取当前左右边界的中间下标
            int temp = left + (right - left) / 2;
            if (nums[temp] > target){
                // 如果中间的树都大于 target,那么右边界向左移动
                right = temp - 1;
            }else if (nums[temp] < target){
                // 如果中甲的树小于 target, 那么左边界移动
                left = temp + 1;
            }else{
                left = temp;
                right = temp;
                while(left > 0 && nums[left - 1 ] == target){
                    left--;
                }
                while(right <= nums.length - 2 && nums[right + 1] == target){
                    right++;
                }
                return new int[]{left, right};
            }
        }
        return new int[]{-1,-1};
    }
}
复制代码

结果提交

网络异常,图片无法展示
|

总结

笑死了,因为偷懒直接 copy的 704的代码,然后缝缝补补,出了好几个 bug,是我自信了,一个小扒菜的自不量力, 但是好在结果是好的

网络异常,图片无法展示
|

在评论区 Carl哥给出了另外一种解法,使用两次二分法查找,分别去查找左边界和右边界,感兴趣的可以试一下

LeetCode 35. 搜索插入位置

题目描述

网络异常,图片无法展示
|

思路分析

  • 依旧是二分法的思路
  • 需要注意的是返回值要是left, 因为当前left > right了证明若存在 target元素就应该在当前的 left下标位置

代码展示

class Solution {
    public int searchInsert(int[] nums, int target) {
        if (nums[0] > target ){
            return 0;
        }
        if (nums[nums.length - 1] < target){
            return nums.length;
        }
        int left = 0, right = nums.length - 1, temp = 0;
        // 因为是二分法,所以当左右双指针相等的时候代表数组遍历完成
        while(left <= right){
            // 获取当前左右边界的中间下标
            temp = left + (right - left) / 2;
            if (nums[temp] > target){
                // 如果中间的树都大于 target,那么右边界向左移动
                right = temp - 1;
            }else if (nums[temp] < target){
                // 如果中甲的树小于 target, 那么左边界移动
                left = temp + 1;
            }else{
                return temp;
            }
        }
         return left ;
    }
}
复制代码

提交结果

网络异常,图片无法展示
|

总结

万万没想到,这道题我竟然错了这么多次,我真的有这么菜的吗。。。

网络异常,图片无法展示
|



目录
相关文章
|
4月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
|
2月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
蓝桥杯Python编程练习题的集合,涵盖了从基础到提高的多个算法题目及其解答。
118 3
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
|
1月前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
2月前
|
机器学习/深度学习 算法 决策智能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
|
2月前
|
算法 C# 索引
C#二分查找算法
C#二分查找算法
|
2月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
77 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
2月前
|
算法 Java C++
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
|
2月前
|
存储 算法 C语言
【C语言】二分查找算法
【C语言】二分查找算法
|
2月前
|
消息中间件 存储 算法
一文搞懂二分查找算法!
一文搞懂二分查找算法!
121 0
|
2月前
|
算法 Java 索引
数据结构与算法学习十五:常用查找算法介绍,线性排序、二分查找(折半查找)算法、差值查找算法、斐波那契(黄金分割法)查找算法
四种常用的查找算法:顺序查找、二分查找(折半查找)、插值查找和斐波那契查找,并提供了Java语言的实现代码和测试结果。
31 0