Day1|二分查找+移除元素

Day1|二分查找+移除元素

二分查找

LeetCode题目链接:https://leetcode.cn/problems/binary-search/

解题思路

  先看题目,已知数组有序,同时数组中每个值唯一。因此只需要考虑一次查询就可以,不用考虑重复的情况。
因此直接可以定义左右边界,并通过每次中间点对应值的情况调整即可。

难点:边界问题

  在每次判断后,进行边界的更新时,容易陷入是边界处理的困惑。例如:当nums[mid] < < <target时,right边界需要进行更新。此时应当是

right = mid;

还是

right = mid - 1;

  要理清这个问题,重点在于理清楚所需要进行再次查询的区间。当区间为(left<=right)时,可以认为是一个左闭右闭区间,此时right值在再次进行查询时,也可能会被查询到。
  因此,判断出nums[mid] < < <target后,可以明确知晓mid所指向的值并不符合要求,因此再次查询时,mid索引自然是不需要的。自然可以得出第二行代码是正确的。
  当区间为(left < < <right)时,可以认为是一个左闭右开区间,此时right值在再次进行查询时,不会被查询到。此时第一行代码是正确的。
AC代码:

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

移除元素

LeetCode题目链接:https://leetcode.cn/problems/remove-element

错误思路

第一时间没有理解数组的删除含义。以为要用erase来进行操作,捣鼓了半天。还打算排个序用二分来搞,尴尬。

解题思路

数组元素在C++底层可以看做是一个连续的存放地址,因此删除数组中的元素,可以看成将这个元素以后的数组元素,进行逐个前移,将该元素覆盖。如果使用Vector容器的话,再将记录容器大小的size减一。自然就实现了代码的删除。
因此,根据以上思路可以直接产生暴力解法:用一个for循环来查找与要删去值相同的元素,再用一个for循环通过移动元素覆盖的方式将元素删除。由于使用了两次for循环,时间复杂度为 O ( n 2 ) O(n^2) O(n2)。具体代码如下:

class Solution {
public:
    int removeElement(vector& nums, int val) {
        int size = nums.size();
        for(int i=0;i

暴力虽然爽但不能多用,想要降低时间复杂度的话,无疑要改变两层for循环的模式,使其尽量在一次for循环中解决覆盖和匹配两个问题。
那么,是不是可以使用两个不同迭代速度的指针来完成该操作呢?便有了快慢指针方法,要删去匹配的元素,即要覆盖掉匹配的元素,从另一种角度可以看成只留下不匹配的元素即可?
即,设置两个索引值,命名为快指针(fast)和慢指针(slow)。其中,快指针负责对数组进行遍历,寻找不匹配元素,慢指针则负责将不匹配的元素对原数组进行覆盖。覆盖就是删除嘛!
这样,最后就可以将原数组用不匹配的元素全部覆盖,同时slow指向新数组的末尾,可以直接作为size来输出。整体时间复杂度为 O ( n ) O(n) O(n)。代码如下:

class Solution {
public:
    int removeElement(vector& nums, int val) {
        int size = nums.size();
        int slow = 0;
        int fast = 0;
        for(;fast

你可能感兴趣的:(数据结构,leetcode,算法,数据结构)