DAY1:数组的二分查找和移除元素

本文详细解释了二分查找算法,包括左闭右开和左闭右开两种情况,以及如何将其应用到LeetCode题目中。同时讨论了移除元素问题的暴力解法和双指针优化方法,强调了时间复杂度分析。
摘要由CSDN通过智能技术生成

二分查找

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

这一块之前写过,所以凭感觉写的不错(笑死我,写的都不是二分法)

其实也就(左闭右开)

class Solution {
public:
    int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size()-1;
while(left<=right){
if(target==nums[left])return left;
else if(target==nums[right])return right;
else{
    left++;
    right--;
}
}
return -1;
    }
};

左闭右闭

class Solution {
public:
    int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size()-1;
while(left<=right){//注意这个是小于等于
if(target==nums[left])return left;
else if(target==nums[right])return right;
else{
    left++;
    right--;
}
}
return -1;
    }
};

以上纯属暴力做法,虽然比纯暴力复杂度少了一半,但是不如二分法

大致思路

二分法(数组是升序或降序的,下以升序为例)应该是,确定一个左边界和有边界,取中间位置的值与target进行比较,而不是左右边界直接向内缩小,如果中间位置的值比target小,则让left=middle,反之,则让right=middle

具体实现

这左闭右闭

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;
    }
};

左闭右开

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
        while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
            int middle = left + ((right - left) >> 1);
            if (nums[middle] > target) {
                right = middle; // target 在左区间,在[left, middle)中
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,在[middle + 1, right)中
            } else { // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};

移除元素

erase函数是删除vector中的某个元素,时间复杂度是O(n);

27. 移除元素 - 力扣(LeetCode)

暴力解决,双重for循环

// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
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;

    }
};

双指针做法

定义两个指针,slow,fast

fast寻找新数组中需要的元素,新数组的下标就是slow

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

后续会按代码随想录的顺序持续更新!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值