6.28 代码随想录训练营第一天 | 数组题目练习:704 二分查找,27移除元素

今天的任务是做两道与数组有关的题,首先来看第一道

Leetcode 704 二分查找
是一道非常经典的题目二分搜索,它的逻辑很简单就是从数组的中间开始,然后要找的数相比,如果中间的数比要找的大那么就向数组的左边移动,如果中间的数比要找的数小就要往数组的右边移动。但是实现二分搜索的首要条件就是这个数组是一个有序数组是从小到大排列的,并且数组中没有重复的元素, 否则就实现不了。

对于这道题,有两种二分搜索的写法

方法 1:在[left, right) 之间查找

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l = 0; 
        int r = nums.size(); // 定义区间[left, right)  
        while(l < r){ //在区间[left, right) left < right 是有效的
            int mid = (l + r) /2;//找到中间的位置
            if(nums[mid] < target) l = mid + 1;//target大,更新区间[left=mid + 1, right]
            else if(nums[mid] > target) r = mid;//target小,更新区间[left, right = mid]
            else return mid;//找到了就返回下标
        }
        return -1;//没找到返回-1
    }
};

方法 2: 在[left, right] 之间查找

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l = 0;
        int r = nums.size() - 1;//定义区间[left,right]
        while(l <= r){ //在区间[left,right]中left==right是有效的
            int mid = (l + r)/2;//找到中间的位置
            if(nums[mid] < target) l = mid + 1;//target大,更新区间[left=mid + 1, right]
            else if(nums[mid] > target) r = mid - 1;//target小,更新区间[left, right = mid -1]
            else return mid;//找到了就返回下标
        }
        return -1;//没找到返回-1
};

本题重点:
这两种方式的不同之处主要体现在target所在的区间之中,一个是在[left, right] 之中此时while语句里的条件为(left <= right),当更新right的时候 r = mid - 1。另外一个是在[left, right) 之中此时while语句里的条件为(left < right), 当更新right的时候 r = mid。


第二题
LeetCode 27 移除元素
是给你一个数,让你移除数组当中的这个数,并且这个数在数组中会重复多次。此题有两种解题方法一种是暴力解法另一种是双指针。暴力解法众所周知是一种非常耗时的方法,因为对于这个题来说要写两个for循环才能完成,所以他的时间复杂度就变成了O(n^2)。一旦数组里有很多的数,就需要很长的时间来运行代码,效率是很低的。

双指针方法

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
       int j = 0; //慢指针j从0开始
       for(int i = 0; i < nums.size();i++){//快指针i遍历整个vector
           if(nums[i] != val){ //如果不是val这个数
               nums[j++] = nums[i];//从下标0开始保存不是val的数,并且更新慢指针
           }
       }
       return j;//返回慢指针下标
    }
};

暴力解法

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;

    }
};

本题思路:
在数组当中元素不能被删除但是可以被覆盖,双指针就是利用数组的这一特性,并将暴力解法的两个for循环变成一个for循环。在这道题中,快指针用来寻找不是val的元素,而慢指针变成了一个新的数组用来存储不是val 的元素。因此在使用的双指针的方法后,时间复杂度就变成了O(n), 效率提高了很多。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值