leetcode刷题记录——移除元素(双指针)

leetcode刷题记录——移除元素

——参考代码随想录和力扣顺序刷题(https://programmercarl.com/)

本质:移动元素;双指针(快慢指针)(左右指针);


文章目录

  27. 移除元素

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

  283. 移动零

  844. 比较含退格的字符串

  977.有序数组的平方


27. 移除元素(简单)

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

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

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

思路1:

  • 将等于val的值移到数组最后方,然后pop_back;

代码1:

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

思路2:双指针(齐头并进,快慢之分)

  • 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新新数组下标的位置
  • 当nums[fastIndex]和val相等,则快指针多走一步,当不相等时,快指针指向的值,覆盖慢指针指向的值。
// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
            if (val != nums[fastIndex]) {
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        return slowIndex;
    }
};

思路3:

  • 双指针(一头一尾,中间靠拢)
  • 一个指针从前一个从后开始遍历,其中(任意)一个指针=val就被另一端!=val的值覆盖。
/**
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int leftIndex = 0;
        int rightIndex = nums.size() - 1;
        while (leftIndex <= rightIndex) {
            // 找左边等于val的元素
            while (leftIndex <= rightIndex && nums[leftIndex] != val){
                ++leftIndex;
            }
            // 找右边不等于val的元素
            while (leftIndex <= rightIndex && nums[rightIndex] == val) {
                -- rightIndex;
            }
            // 将右边不等于val的元素覆盖左边等于val的元素
            if (leftIndex < rightIndex) {
                nums[leftIndex++] = nums[rightIndex--];
            }
        }
        return leftIndex;   // leftIndex一定指向了最终数组末尾的下一个元素
    }
};

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


26. 删除有序数组中的重复项(简单)

思路:

  • 双指针,快慢指针,一开始快慢指针指向同一个值,快指针每次循环+1,慢指针只有在nums[slowIndex] != nums[fastIndex]才会+1,并且将nums[fastIndex]的值覆盖到nums[slowIndex]上(因为当不相等时,slowIndex先+1,所以保证不会覆盖掉唯一的数字);
  • 如果相等,q 后移 1 位
    如果不相等,将 q 位置的元素复制到 p+1 位置上,p 后移一位,q 后移 1 位
    重复上述过程,直到 q 等于数组长度。
  • 因为返回数组长度,所以返回slowIndex + 1;

代码:

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

283. 移动零(简单)

将0移到最后的位置;

思路:

  • 双指针,不等于0和0交换,若等于0,slowIndex不移动,保持slowIndex始终指向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]);
                slowIndex++;
            }
        }
        return;
    }
};

844. 比较含退格的字符串(简单)

思路:

  • 使用栈思想,如果当前字符不是 ‘#’ 则加入,如果是,则弹出;(string可以当栈使用);

代码:

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        string S,T;
        for(int i=0;i<s.length();i++) {
            if(s[i] != '#') {
                S += s[i];
            }
            else {
                if(!S.empty())
                S.pop_back();
            }
        }
        for(int i=0;i<t.length();i++) {
            if(t[i] != '#') {
                T += t[i];
            }
            else {
                if(!T.empty())
                T.pop_back();
            }
        }
        if(T == S) return true;
        else return false;
    }
};

977. 有序数组的平方(简单)

思路1:

  • 将数组平方后排序。

思路2:

  • 双指针(两边靠近),新开一个数组,常识可得,两边的平方更大,则一个left指针在0,right指针在size-1的位置向中间靠近,两个比较,谁大则谁逆序进入ans数组;
  • 需要一个k来进行计数,还需要新开一个数组,临界条件是left <= right(要将最后一个数字(最小的)填进数组;
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int right = nums.size() - 1;
        int k = nums.size() - 1;
        int left = 0;
        vector<int> ans(nums.size(), 0);
        while(left <= right) {
            if(nums[left] * nums[left] > nums[right] * nums[right]) {
                ans[k--] = nums[left] * nums[left];
                left++;
            }
            else {
                ans[k--] = nums[right] * nums[right];
                right--;
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值