代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素

一、Leetcode 704 二分查找

题目链接:Leetcode704

这个题目在之前秋招准备的时候就刷了,好几个月没刷又忘了这个题目的思想,二分法的使用前提是有序数组,这里主要是看查找区间是左闭右闭还是左闭右开,这两种方法都可以,不同方法对应着不同的while循环条件(是left<=还是<)和变量(mid的变化和right的初始化)

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

二、Leetcode 27 移除元素

题目链接:Leetcode 27

这个题也是秋招的时候学过的一道题目,代码随想录上给出了两种方法,我自己额外用了一个栈的方法,一个是暴力的两层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;

    }
};

第二种是我的方法,在遍历数组的时候将不等于val的值push进栈,然后再遍历一遍重新pop出来

// 时间复杂度:O(n)
// 空间复杂度:O(n)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        stack<int> st;
        int count=0,i=0;
        for(i;i<nums.size();i++){
            if(nums[i]!=val){
                st.push(nums[i]);
                count++;
            }else{
                nums[i]=-1;
            }
        }
        i=0;
        while(!st.empty() ){
            nums[i]=st.top();
            st.pop();
            i++;
        }
        return count;
    }
};

第三个方法就是要重点掌握的双指针法,快指针寻找新的要移动的元素,慢指针提供索引进行交换,保证数组前都是非val的元素

// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        if(nums.size()==0) return NULL;
        int left=0,right=0;
        while(right<=nums.size()-1){
            if(nums[right]!=val){
                nums[left++]=nums[right];
            }
            right++;
        }
        return left;
    }
};

总结

这两道题当时秋招的时候感觉都挺熟悉的,这两种方法在之前刷题的时候也在其他题里面用过,无奈也是忘了具体咋做,感觉做的时候给我的感觉就是很模糊,自己懂大概咋做呢,但是就只知道一半,给人一种若隐若现的感觉,还是理解的不够深入,之后如果还有新的理解再在这个文章里记录下来

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