[代码随想录]数组--移除元素

移除元素

解决方法

1.暴力解法

两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。代码实现看例27

在这里插入图片描述
时间复杂度:O(n^2)
空间复杂度:O(1)

2.双指针法

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

定义快慢指针

快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
慢指针:指向更新 新数组下标的位置
代码实现看例题

在这里插入图片描述
时间复杂度:O(n)
空间复杂度:O(1)

下面为leetcode上例题

27.移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

1.暴力解法

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

2.改进一点点

因为内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    
    
    print(nums[i]);
}

所以

class Solution {
    
    
public:
    int removeElement(vector<int>& nums, int val) {
    
    
        int count = nums.size();
        for(int i = nums.size() - 1;i >= 0;i--){
    
    
            if(nums[i] == val ){
    
    
                count--;
                for(int j = i + 1;j < nums.size() ;j++){
    
    //因为内部主函数是根据返回的const为数组中的元素个数,如果最后一个数是目标数,自然而然会把最后一个数删除
                    nums[j - 1] = nums[j];
                }
            }
        }
        return count;
    }
};

3.双指针法

//不改变数组顺序
class Solution {
    
    
public:
    int removeElement(vector<int>& nums, int val) {
    
    
        int slowIndex = 0;
        for(int fastIndex = 0;fastIndex < nums.size(); fastIndex++){
    
    
            if(nums[fastIndex] != val){
    
    
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex; 
    }
};

//改变数组顺序
class Solution {
    
    
public:
    int removeElement(vector<int>& nums, int val) {
    
    
        int leftIndex = 0;
        int rightIndex = nums.size() - 1;
        while(leftIndex <= rightIndex){
    
    
            while(leftIndex <= rightIndex && nums[leftIndex] !=val){
    
    
                leftIndex++;
            }
            while(leftIndex <= rightIndex && nums[rightIndex] == val){
    
    
                rightIndex--;
            }
            if(leftIndex < rightIndex){
    
    
                nums[leftIndex] = nums[rightIndex];
                leftIndex++;
                rightIndex--;
            }
        }       
        return leftIndex;
    }
};

26. 删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你** 原地** 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

1.暴力解决

class Solution {
    
    
public:
    int removeDuplicates(vector<int>& nums) {
    
    
        int count = nums.size();
        for(int i = nums.size() - 1;i > 0;i--){
    
    
            if(nums[i] == nums[i - 1]){
    
    
                for(int j = i;j < count;j++){
    
    
                    nums[j - 1] = nums[j];
                }
                 count--;
            }
        }
        return count;
    }
};

2.双指针法

class Solution {
    
    
public:
    int removeDuplicates(vector<int>& nums) {
    
    
        int slowIndex = 0;
        for(int fastIndex = 1;fastIndex < nums.size();fastIndex++){
    
    
            if(nums[fastIndex] != nums[fastIndex - 1]){
    
    
                nums[slowIndex + 1] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex + 1;
    }
};

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

1.双指针法,将非零移到一边,后面直接补零

class Solution {
    
    
public:
    void moveZeroes(vector<int>& nums) {
    
    
        int slowIndex = 0;
        for(int fastIndex = 0;fastIndex < nums.size();fastIndex++){
    
    
            if(nums[fastIndex] != 0){
    
    
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        for(int i = slowIndex;i < nums.size();i++){
    
    
            nums[i] = 0;
        }
    }
};

2.双指针法,遇到0就交换两个数字位置

class Solution {
    
    
public:
    void moveZeroes(vector<int>& nums) {
    
    
        int slowIndex = 0;
        for(int fastIndex = 0;fastIndex < nums.size();fastIndex++){
    
    
            if(nums[fastIndex] != 0){
    
    
                swap(nums[slowIndex++],nums[fastIndex]);
            }
        }
    }
};

844. 比较含退格的字符串

给定 st 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true# 代表退格字符。

**注意:**如果对空文本输入退格字符,文本继续为空。

要考虑情况很多:1.没有#时,2.第一个字符为#,3.连续两个#,但是前面没有可删数字 , 4.连续两个#,但是前面有可删数字,5.其他情况

1.双指针法,暴力破解

class Solution {
    
    
public:
    bool backspaceCompare(string s, string t) {
    
    
        int slowIndex = 0;
        int i = s.length(),j = t.length();
        for(int fastIndex = 0;fastIndex < s.length();fastIndex++){
    
    
            if(s[fastIndex] != '#'){
    
    
                s[slowIndex] = s[fastIndex];
                slowIndex++;
            }
            else if(fastIndex == 0 ||(s[fastIndex - 1] == '#' && slowIndex == 0)){
    
    
                i--;
            }
            else{
    
    
                slowIndex--;
                i = i - 2;
            }
        }
        slowIndex = 0;
         for(int fastIndex = 0;fastIndex < t.length();fastIndex++){
    
    
            if(t[fastIndex] != '#'){
    
    
                t[slowIndex] = t[fastIndex];
                slowIndex++;
            }
            else if(fastIndex == 0 || (t[fastIndex - 1] == '#' && slowIndex == 0)){
    
    
                j--;
            }
            else{
    
    
                slowIndex--;
                j = j - 2;
            }
        }
        if(s.substr(0,i) == t.substr(0,j)){
    
    
            return true;
        }
        else return false;

    }
};

2.重构字符串 主要想到尾插和尾删

class Solution {
    
    
public:
    bool backspaceCompare(string s, string t) {
    
    
        return getNewString(s) == getNewString(t);
    }

    string getNewString(string x){
    
    
        string s;
        for(auto val:x){
    
    
            if(val != '#'){
    
    
                s.push_back(val);
            }
            else if(s.length() > 0){
    
    
                s.pop_back();
            }
        }
        return s;
    }
};

977.有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

1.先平方,在排序

2.扩展一个新空间,双指针法,每次把最大的放进新数组

class Solution {
    
    
public:
    vector<int> sortedSquares(vector<int>& nums) {
    
    
        int leftIndex = 0,index = nums.size() - 1;
        vector<int> v(index + 1);
        for(int rightIndex = nums.size() - 1;rightIndex >= leftIndex;){
    
    
            if(nums[rightIndex] * nums[rightIndex] > nums[leftIndex] * nums[leftIndex]){
    
    
                v[index--] = nums[rightIndex] * nums[rightIndex];
                rightIndex--;
            }
            else{
    
    
                v[index--] = nums[leftIndex] * nums[leftIndex];
                leftIndex++;
            }
        }
        return v;
    }
};

猜你喜欢

转载自blog.csdn.net/m0_53953432/article/details/127930334
今日推荐