代码随想录Day3-数组-移除元素:力扣26、283、844题

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

题目链接

方法一:快慢双指针

思路

设置快指针fast和慢指针slowfast负责检测元素是否重复,不重复则将其赋值给nums[slow]

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)
C++代码
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int size = nums.size();
        if (size <= 1) {
            return size;
        }
        int slow = 1;
        int fast = 1;

        while (fast < size) {
            if (nums[fast] == nums[fast - 1]) {
                ++fast;
            } else {
                nums[slow++] = nums[fast++];
            }
        }
        return slow;
    }
};

看完讲解的思考

代码实现遇到的问题


283. 移动零

题目链接

方法一:快慢双指针

思路

设置快指针fast和慢指针slowfast负责检测元素是否为0,不为0则交换nums[slow]nums[fast],将非0元素移动到左端。

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)
C++代码
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int size = nums.size();
        if (size <= 1) {
            return;
        }
        int slow = 0;
        int fast = 0;

        while (fast < size) {
            if (nums[fast] == 0) ++fast;
            else swap(nums[slow++], nums[fast++]);
        }
        return;
    }
};

看完讲解的思考

代码实现遇到的问题


844. 比较含退格的字符串

题目链接

方法一:栈

思路

先分别计算两个输入会得到的字符串,再比较两个结果是否相等。
用栈来计算字符串的结果,遍历输入的每一个字符,如果不是#则入栈,如果是#则弹出栈顶字符,最终得到存储在栈中的字符串结果。

  • 时间复杂度: O ( n + m ) O(n+m) O(n+m),n和m分别为两个字符串的长度。
  • 空间复杂度: O ( n + m ) O(n+m) O(n+m),存储字符串结果的栈需要用到与输入同量级的空间。
C++代码
class Solution {
public:
    bool backspaceCompare(string s, string t) {
        stack<char> s1 = getResult(s);
        stack<char> s2 = getResult(t);
        return s1 == s2;
    }

private:
    stack<char> getResult(string input) {
        int size = input.size();
        stack<char> res;
        for (int i = 0; i < size; ++i) {
            if (input[i] != '#') {
                res.push(input[i]);
            } else {
                if (!res.empty()) res.pop();
            }
        }
        return res;
    }
};

方法二:双指针原地修改字符串后一一比较

思路

自己想到的一个另类做法,当时是想着需要空间复杂度为 O ( 1 ) O(1) O(1),用栈来保存字符串结果的话需要开辟额外空间,所以就想着原地修改字符串,这样就可以满足空间复杂度为 O ( 1 ) O(1) O(1)
原地修改字符串使得字符串右端为字符串结果,并返回字符串结果的长度,然后依次遍历字符串结果比较是否相等。
整体思路与方法一类似,只是把开辟额外空间存储结果改为了原地修改。

  • 时间复杂度: O ( 2 ( n + m ) ) O(2(n+m)) O(2(n+m)),修改的时候需要遍历一次,比较的时候又需要遍历一次。
  • 空间复杂度: O ( 1 ) O(1) O(1)
C++代码
class Solution {
public:
    bool backspaceCompare(string s, string t) {
        int sSize = getFinalString(s);
        int tSize = getFinalString(t);
        if (sSize != tSize) return false;
        for (int i = 0; i < sSize; ++i) {
            if (s[i] != t[i]) return false;
        }
        return true;
    }

private:
    int getFinalString(string& s) {
        int slow = 0;
        int fast = 0;
        int size = s.size();

        while (fast < size) {
            if (s[fast] == '#') {
                ++fast;
                if (slow > 0) {
                    --slow;
                }
            } else {
                s[slow++] = s[fast++];
            }
        }
        return slow;
    }
};

方法三:双指针一次遍历

思路

因为#只会影响前面的字符,不会影响后面的字符,所以对于两个字符串分别设立指针,从后往前遍历字符串。分别找到当前字符,比较两字符是否相等,不相等则返回false,若是其中一个字符串已经遍历完了,另外一个还没有,则也是返回false。

  • 时间复杂度: O ( n + m ) O(n+m) O(n+m)
  • 空间复杂度: O ( 1 ) O(1) O(1)
C++代码

自己一开始实现的双指针(又臭又长…但总归是AC了)

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        int s_idx = s.size() - 1;
        int t_idx = t.size() - 1;
        int s_pass = 0;
        int t_pass = 0;

        while (s_idx >= 0 && t_idx >= 0) {
            if (s[s_idx] == '#') {
                --s_idx;
                ++s_pass;
            } else if (t[t_idx] == '#') {
                --t_idx;
                ++t_pass;
            } else if (s_pass > 0) {
                --s_idx;
                --s_pass;
            } else if (t_pass > 0) {
                --t_idx;
                --t_pass;
            } else if (s[s_idx] != t[t_idx]) {
                return false;
            } else {
                --s_idx;
                --t_idx;
            }
        }
        while (s_idx >= 0) {
            if (s[s_idx] == '#') {
                --s_idx;
                ++s_pass;
            } else if (s_pass > 0) {
                --s_idx;
                --s_pass;
            } else {
                return false;
            }
        }
        while (t_idx >= 0) {
            if (t[t_idx] == '#') {
                --t_idx;
                ++t_pass;
            } else if (t_pass > 0) {
                --t_idx;
                --t_pass;
            } else {
                return false;
            }
        }
        return true;
    }
};

简洁版

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        int s_idx = s.size() - 1;
        int t_idx = t.size() - 1;
        int s_pass = 0;
        int t_pass = 0;

        while (s_idx >= 0 || t_idx >= 0) {
            // 找到当前字符
            while (s_idx >= 0) {
                if (s[s_idx] == '#') --s_idx, ++s_pass;
                else if (s_pass > 0) --s_idx, --s_pass;
                else break;
            }
            while (t_idx >= 0) {
                if (t[t_idx] == '#') --t_idx, ++t_pass;
                else if (t_pass > 0) --t_idx, --t_pass;
                else break;
            }
            // 判断两字符是否相等
            if (s_idx >= 0 && t_idx >= 0) {
                if (s[s_idx] != t[t_idx]) return false;
            } else {
                if (s_idx >= 0 || t_idx >= 0) return false;
            }
            --s_idx, --t_idx;
        }
        return true;
    }
};

看完讲解的思考

代码实现遇到的问题

方法三一开始实现用了三块while循环,没有想到怎么把这个三个while统一到一个while中


最后的碎碎念

昨晚出去聚餐了,导致刷了一半中断,第二天一早才补上,今天得双更了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值