代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素、34.在排序数组中查找元素的第一个和最后一个位置、35.搜索插入位置。

力扣704.二分查找

题目链接:704. 二分查找 - 力扣(LeetCode)

思路:在二分查找的过程中,循环不变量原则,要搞清楚边界定义,我习惯用左闭右闭的区间。

C++代码:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size()-1;
       while(left<=right){
           int mid=left+(right-left)/2;
           if(nums[mid]<target){
               left=mid+1;
           }
           else if(nums[mid]>target){ //if和else if执行是互斥的
               right=mid-1;
           }
           else
           return mid;
       }
        return -1;
    }
};

力扣27.移除元素

题目链接:27. 移除元素 - 力扣(LeetCode)

思路:双指针法回顾,分别定义快慢指针,快指针遍历整个数组,寻找不含有需要删除的元素的新数组,慢指针就是用来指向更新后的新数组

C++代码:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
       
        int slowindex=0;
        for(int fastindex=0;fastindex<nums.size();fastindex++){
            if(val!=nums[fastindex]){
                nums[slowindex]=nums[fastindex];
                slowindex++;
            }
        }
        return slowindex;
    }
};

 力扣35.搜索插入位置

题目链接:35. 搜索插入位置 - 力扣(LeetCode)

思路:由于本道题目要求的特殊性,nums为无重复元素的升序数组,只需要查找数组中第一个大于等于目标元素的下标位置即可,所以使用暴力法遍历整个数组效率很高。另一种方法还是使用二分法,中间条件判断与704题类似,我习惯按照左闭右闭区间,最后返回值需要考虑到四种情况。

C++代码:

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size()-1;
        while(left<=right){
            int mid=left+(right-left)/2;

            if(nums[mid]>target){
                right=mid-1;
            }
            else if(nums[mid]<target){
                left=mid+1;
            }
            else return mid;
        }
        // 分别处理如下四种情况
        // 目标值在数组所有元素之前  [0, -1]
        // 目标值等于数组中某一个元素  return middle;
        // 目标值插入数组中的位置,return  right + 1
        // 目标值在数组所有元素之后的情况 , 因为是右闭区间,所以 return right + 1
        return right+1;
    }
};

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

题目链接:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

思路:本质还是二分查找,只不过由于数组中存在相同的元素,需要找出相同元素的起始位置和结束位置。构造两个函数分别确定左边界和右边界。(找target的右边界时,而left=mid+1,是往右移动的,然后下次移动是在target大于等于mid位置的元素时候,以此类推,直到退出循环)

C++代码:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int rBorder=getRightBorder(nums,target);
         int lBorder=getLeftBorder(nums,target);
        // 情况一  target在数组范围的左边或右边
        if (lBorder == -2 || rBorder == -2) return {-1, -1};
        // 情况三   target在数组中
        if (rBorder - lBorder > 1) return {lBorder + 1, rBorder - 1};
        // 情况二   target在数组范围内,但没有相同元素
        return {-1, -1};
    }
private:
    int getRightBorder(vector<int>&nums,int target){
        int left=0;
        int right=nums.size()-1;
        int rBorder=-2;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]>target){
                right=mid-1;
            }
            else{
                left=mid+1;
                rBorder=left;
            }
        }
        return rBorder;
    }
     int getLeftBorder(vector<int>&nums,int target){
        int left=0;
        int right=nums.size()-1;
        int lBorder=-2;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]>=target){
                right=mid-1;
                lBorder=right;
            }
            else{
                left=mid+1;   
            }
        }
        return lBorder;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值