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

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

一、前言

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

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

闲话少说, 今天是算法训练营的第一天,目标是【数组】模块 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 ;
    }
}
复制代码

提交结果

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

总结

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

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



目录
相关文章
|
2月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
|
2月前
|
存储 算法 Java
深入算法基础二分查找数组
文章深入学习了二分查找算法的基础,通过实战例子详细解释了算法的逻辑流程,强调了确定合法搜索边界的重要性,并提供了Java语言的代码实现。
深入算法基础二分查找数组
|
3月前
knn增强数据训练
【7月更文挑战第27天】
29 10
|
3月前
|
数据采集 编解码 人工智能
破解ChatGPT惊人耗电!DeepMind新算法训练提效13倍,能耗暴降10倍
【7月更文挑战第19天】DeepMind的JEST算法革新AI训练,提升效率13倍,节能10倍。通过联合数据批次选择,预训练指导及多分辨率训练,优化资源利用,降低能耗。实验显示性能提升,达到SOTA水平,但实施需大量资源,依赖优质参考模型。[论文链接](https://arxiv.org/pdf/2406.17711)
58 10
|
3月前
knn增强数据训练
【7月更文挑战第28天】
23 2
|
2月前
|
算法 搜索推荐
支付宝商业化广告算法问题之基于pretrain—>finetune范式的知识迁移中,finetune阶段全参数训练与部分参数训练的效果如何比较
支付宝商业化广告算法问题之基于pretrain—>finetune范式的知识迁移中,finetune阶段全参数训练与部分参数训练的效果如何比较
|
3月前
|
人工智能 边缘计算 算法
破解ChatGPT惊人耗电!DeepMind新算法训练提效13倍,能耗暴降10倍
【7月更文挑战第20天】DeepMind unveils Switch Transformer, revolutionizing AI energy consumption. This novel algorithm boosts training efficiency by 13x and slashes energy use by 10x compared to ChatGPT, marking a significant leap towards eco-friendly AI.
40 2
|
2月前
|
算法
【算法】二分查找——二分查找
【算法】二分查找——二分查找
|
2月前
|
存储 算法
【C算法】编程初学者入门训练140道(1~20)
【C算法】编程初学者入门训练140道(1~20)
|
3月前
|
算法
【算法】二分查找(整数二分和浮点数二分)
算法学习——二分查找(整数二分和浮点数二分)
32 0
【算法】二分查找(整数二分和浮点数二分)
下一篇
无影云桌面