2022-1-11 LeetCode 双指针1

力扣复健第一天~从看似比较简单的双指针开始(实际并没有)

27.移除元素

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

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

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

1. 快慢指针

这也是比较经典和舒服的解法,但是第一次思考觉得还是有点困难(x

注意slow指针只负责统计数量,把符合条件的一个个填充到slow指针指的地方。
而fast指针是循环变量,同时也是判断的关键,判断是不是val

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n=nums.size();
        int slow=0,fast=0;
        for(fast=0;fast<n;fast++)
        {
            if(nums[fast]!=val)
            {
                nums[slow++]=nums[fast];
            }
        }

        return slow;

    }
};

2. 从后往前的双指针

这是元素替代一题想到的方法,一个指针i指向要填充的地方,j从后往前对i处进行填充。注意j处一定不能是val,所以一定要先用循环把它过滤一下,最初的j一定要指向非val

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n=nums.size();
        if(n<=0) return 0;
        // i指向当前,j指向末尾
        int j=n-1;
        while(j>=0&&nums[j]==val)
        {
            j--;
        }


        for(int i=j;i>=0;i--)
        {
            if(nums[i]==val)
            {
                nums[i]=nums[j];
                j--;
            }
        }


        return j+1;

    }
};

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

继续贯彻了上一题快慢指针的思想:
注意slow指针只负责统计数量,把符合条件的一个个填充到slow指针指的地方。
而fast指针是循环变量,同时也是判断的关键 到底该不该把fast上的元素给slow,就看fast指针指的值是否符合要求。
这题里,如果fast指针的上一个值和现在的值不同,说明这是一个“边界”,也就是新值,非重复值,此时可以赋给nums[slow]

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int n=nums.size();
        if(n==0||n==1) return n;
        int slow=1,fast=1;

        while(slow<n&&fast<n)
        {
            if(nums[fast]!=nums[fast-1])
            {
                nums[slow]=nums[fast];
                slow++;
            }

            fast++;

        }
        return slow;


    }
};

844.比较含退格的字符串

这题的要求是空间O(1)
如果是O(m+n) 那么我们开两个字符串,存入最终结果比较一下就好了

1. 空间O(m+n)

ps.用栈更方便

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        int spos=-1,tpos=-1;
      //  int lens=s.length(),lent=t.length();
        string ss,tt;

        for(char c:s)
        {
            if(c!='#')
            {
                ss+=c;
                spos++;
            }
            else
            {
                if(spos>=0)
                {
                    ss.erase(spos,1);
                    spos--;
                }
            }
        }

        for(char c:t)
        {
            if(c!='#')
            {
                tt+=c;
                tpos++;
            }
            else
            {
                if(tpos>=0)
                {
                    tt.erase(tpos,1);
                    tpos--;
                }
            }
        }
       // cout<<ss<<" "<<tt<<endl;
        return tt==ss;

    }
};

2. 空间O(1)

复健第一天表示还是难写啊qaq

  1. 先找到s中第一个要比较的字符
  2. 找t中第一个要比较的字符
  3. i>=0 j>=0的条件下(防止第一个字符为# 那么下标减出来是负数) 如果两个字符比较为不同,立刻false
  4. i,j一种已经到头,另一种没到,说明没匹配上,也是false
  5. i–,j-- 下一个循环
class Solution {
public:
    bool backspaceCompare(string s, string t) {
        int lens=s.length();
        int lent=t.length();
        int i=lens-1;
        int j=lent-1;
        int skipS=0,skipT=0;
        while(i>=0||j>=0)
        {
            //找到S中的第一个可比较字符
            while(i>=0)
            {
                if(s[i]=='#')
                {
                    skipS++;
                    i--;
                }
                else if(skipS>0)
                {
                    skipS--;
                    i--;
                }
                else break;
            }
//找到T中的第一个可比较字符位置
            while(j>=0)
            {
                if(t[j]=='#')
                {
                    skipT++;
                    j--;
                }
                else if(skipT>0)
                {
                    skipT--;
                    j--;

                }
                else break;
            }

            if(i>=0&&j>=0)
            {
                if(s[i]!=t[j]) return false;
            }
            else if(i>=0||j>=0)
            {
                return false;
            }
            i--;j--;

        }

        return true;

    }
};

977. 有序数组的平方

最大值只能是在数组的两遍,所以用两个指针,一个指向最左,一个最右。
开一个同样大小的数组,从末尾向前填空

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int n=nums.size();
        vector<int> res(n,0);

        int i=0,j=n-1;
        int pos=n-1,t1,t2;

        while(i<=j)
        {
            t1=nums[i]*nums[i];
            t2=nums[j]*nums[j];
            if(t1>=t2)
            {
                res[pos--]=t1;
                i++;
            }
            else
            {
                res[pos--]=t2;
                j--;
            }
            
        }

        return res;
        

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值