力扣刷题记录

01二分查找

力扣链接
几个注意点

  • 1.设置三个变量,【left,right】区间的左右值,以及区间中点middle;
  • 2.注意左闭右闭与左闭右开对几个变量的影响
  • 3.返回-1是在while循环结束还未找到target值时执行的,因此在while循环结束之后执行的
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        while(left <= right){
            int middle = (left + right)/2;
            if(target < nums[middle]){
                right = middle -1;
            }
            else if(target > nums[middle]){
                left = middle +1;
            }
            else{
                return middle;
            }
        }
        return -1;
    }
};

02利用二分查找搜索插入位置

力扣链接

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size()-1;
    while(left <= right){
        int middle = (left + right)/2;
        if(target < nums[middle]){
            right = middle - 1;
        }
        else if(target > nums[middle]){
            left = middle + 1;
        }
        else if(target == nums[middle]){
            return middle;
        }
    }
    return right + 1;
    }
};
  • 注意最后的return right + 1 为什么要+1,因为设置的循环条件是left <= right,所以最后一个循环时left与right值相同,会再执行一次right = middle - 1;语句
  • 只要看到面试题里给出的数组是有序数组,都可以考虑使用二分法。最好是无重复的数组,因为重复数组二分法返回数值不唯一

03查找数组中一个元素的第一个位置和最后一个位置(二分法)

力扣链接

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.empty()) return {-1,-1};
    
        int l = 0, r = nums.size() - 1; //二分范围
        while( l < r)			        //查找元素的开始位置
        {
            int mid = (l + r )/2;
            if(nums[mid] >= target) r = mid;
            else l = mid + 1;
        }
        if( nums[r] != target) return {-1,-1};  //查找失败
        int L = r;
        l = 0, r = nums.size() - 1;     //二分范围
        while( l < r)                   //查找元素的结束位置
        {
            int mid = (l + r + 1)/2;
            if(nums[mid] <= target ) l = mid;
            else r = mid - 1;
        }
        return {L,r};
    }
};

细节太多,做吐了

04移除元素

力扣链接
暴力法:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        for (int i = 0; i < size; i++) {
            if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
                for (int j = i + 1; j < size; j++) {
                    nums[j - 1] = nums[j];
                }
                i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
                size--; // 此时数组的大小-1
            }
        }
        return size;

    }
};
  • 需要注意的是如果按下文编写,比如数组十个元素,l = i = 9时,nums[9] = nums[10];显然越位了。(朝哥,你就是我的神!)
for (int l = i; l < len; l++){
                    nums[l] = nums[l + 1];
                }

双指针法:

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];
            }
        }
        return slowIndex;
    }
};
  • i++是先取i的值再+1,如a=i++是先进行a=i的赋值操作,然后i+1
  • ++i则相反,先进行i+1然后再取i的值
    i++与++i区别
posted @ 2022-05-30 15:59  零度加冰  阅读(35)  评论(0)    收藏  举报