• 【算法挨揍日记】day09——704. 二分查找、34. 在排序数组中查找元素的第一个和最后一个位置


     

     704. 二分查找 

    704. 二分查找

    题目描述: 

    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 

    解题思路: 

    本题数组是有序的,具有二段性,因此我们可以使用二分算法来解决这个问题

    值得注意的是:当left和right不断向中间移动的过程中,left和right可能指向同一个位置,而这个位置需要判断,因此我们的循环条件为left<=right

     解题代码:

    1. class Solution {
    2. public:
    3. int search(vector<int>& nums, int target) {
    4. int left=0;
    5. int right=nums.size()-1;
    6. while(left<=right)
    7. {
    8. int mid=left+(right-left)/2;
    9. if(nums[mid]==target) return mid;
    10. if(nums[mid]>target) right=mid-1;
    11. if(nums[mid]1;
    12. }
    13. return -1;
    14. }
    15. };

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

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

     题目描述:

    给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

    如果数组中不存在目标值 target,返回 [-1, -1]

    你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

    解题思路:

    本题我们利用二分来解决左右端点的问题,首先left和right肯定有的

    我们通过一个示例来了解本题:[1,2,3,3,3,4,5]

    查找左端点:我们这里用t来代替target(这样比较好叙述)

    • 二分的思路操作:我们可以将上述示例分为两个部分,因为我们现在查找左端点,因此我可以将示例分为【[1,2],[3,3,3,4,5]

    1. 当x
    2. 当x>=t时,处于【3,3,3,4,5】这个区间,right=mid(这里不能等于mid-1,因为如果mid=0,right=-1会越界)
    • 细节处理:

    循环条件:

    1. left
    2. left<=right   ×

    我们选择那种呢?我们来讨论一下:

    1. 有结果
    2. 全大于t(t1),right一直向左走,最后right为left结束,如果是left<=right会死循环
    3. 全小于t(t2),left一直向右走,最后left在right右边结束

    以此我们只能选择第一种不能选择第二种!

    求中间的操作:

    1. left+(right-left)/2        ×
    2. left+(right-left+1)/2    

    我们考虑一下极端情况就可以知道了!当只剩下两个元素的时候:

    第一种没有问题,第二种mid=0+2/2=1,当进行left+1操作的时候会发生越界

    查找右端点

    • 二分的思路操作:我们可以将上述示例分为两个部分,因为我们现在查找左端点,因此我可以将示例分为【[1,2,3,3,3].[4,5]

    1. 当x<=t时,处于【1,2,3,3,3】这个区间,left=mid
    2. 当x>t时,处于【4,5】这个区间,right=mid-1
    • 细节处理:

    循环条件:

    1. left
    2. left<=right   ×

    还是选择left

    求中间的操作:

    1. left+(right-left)/2        
    2. left+(right-left+1)/2    ×

    我们考虑一下极端情况就可以知道了!当只剩下两个元素的时候:

    第一种当mid=0+1/2=0时,right=mid-1越界,第二种没有问题

    解题代码:

    1. class Solution {
    2. public:
    3. vector<int> searchRange(vector<int>& nums, int target) {
    4. //特殊情况处理一下
    5. if(nums.size()==0)return {-1,-1};
    6. int left=0,right=nums.size()-1;
    7. vector<int> ret;
    8. //查找左端点
    9. while(left
    10. {
    11. int mid=left+(right-left)/2;
    12. if(nums[mid]1;
    13. if(nums[mid]>=target)right=mid;
    14. }
    15. //当left==right时就是结果
    16. if(nums[left]!=target)return {-1,-1};
    17. else ret.push_back(left);
    18. //查找右端点
    19. left=0,right=nums.size()-1;
    20. while(left
    21. {
    22. int mid=left+(right-left+1)/2;
    23. if(nums[mid]<=target)left=mid;
    24. if(nums[mid]>target)right=mid-1;
    25. }
    26. if(nums[right]!=target)return {-1,-1};
    27. else ret.push_back(right);
    28. return ret;
    29. }
    30. };

     

  • 相关阅读:
    C++ 类和对象 (5) 析构函数
    win10+yolov5+pytorch+gpu
    手把手教你用Python操纵Word自动编写离职报告
    学Python的漫画漫步进阶 -- 第十一步.常用的内置模块
    与“客户”沟通技巧
    网工内推 | 急招网工,思科、华为认证优先,法定节假日三薪
    题目:一个整数,它加上100 后是一个完全平方数, 再加上168 又是一个完全平方数,请问该数是多少?
    力扣-43题 字符串相乘(C++)- 大数相乘
    QT动态加载qss和rcc方式
    修改pip默认安装位置
  • 原文地址:https://blog.csdn.net/m0_69061857/article/details/133323980