LeetCode系列:双指针法

双指针法(双循环变量法)

一、快慢指针(同向指针)

例1:27. 移除元素

链接:https://leetcode-cn.com/problems/remove-element

给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

总结:所有“原地”操作的空间复杂度均为 O(1),这一类算法就是使用快慢指针,建立基于慢指针索引的数组覆盖掉原数组,不必开辟额外空间。**

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

思考1:如果返回值写为 “return nums.size();” 是否正确?

错误,因为vector< int >初始化的是一个固定长度的数组,在函数执行的过程中只是修改了数组的元素,并没有修改固定数组的长度。如果想要返回移除后的数组,应使用可变长度的动态数组实现,或者使用vector中的resize(j)方法。

思考2:若数组是无序的,如何设计算法?


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

链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array

给你一个有序数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

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

思考:下列算法是否正确?

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

例3:283. 移动零

链接:https://leetcode-cn.com/problems/move-zeroes

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

思考:下列算法的时间复杂度为多少?能否提高该算法的效率?

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

例4:844. 比较含退格的字符串

链接:https://leetcode-cn.com/problems/backspace-string-compare

给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,请你判断二者是否相等。# 代表退格字符。如果相等,返回 true;否则,返回 false 。注意:如果对空文本输入退格字符,文本继续为空。

方法一:同向指针法

从前面开始比较,如果不是退格,就放进Buffer中,如果出现了退格,就在Buffer中删除一个元素,原地删除数据就是将数组的第二下标往首地址移动(从前往后存数据,从后往前删数据)。

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        backspaceString(s);
        backspaceString(t);
        return s==t;
    }
    void backspaceString(string &s)
    {
        int j = 0;
        for(int i = 0; i < s.length(); i++)
        {
            if(s[i] != '#')		//注意使用if-else if-else非此即彼的性质
            {
                s[j] = s[i];
                j++;
            }
            else if(j != 0)		//隐含了对backspace的判断
                j--;
        }
        s.resize(j);
    }
};

方法二:利用栈来实现

这里是引用


二、对立指针

例5:344. 反转字符串

链接:https://leetcode-cn.com/problems/reverse-string

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组,使用 O(1) 的额外空间解决这一问题。

class Solution {
public:
    void reverseString(vector<char>& s) {
        int i, j;
        i = 0;
        j = s.size()-1;
        while(i < j)
        {
            char temp = s[i];
            s[i] = s[j];
            s[j] = temp;
            i++;
            j--;
        }
    }
};

例6:977. 有序数组的平方

链接:https://leetcode-cn.com/problems/squares-of-a-sorted-array

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

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int a, b, k;
        a = 0;
        b = nums.size()-1;
        k = nums.size()-1;
        vector<int> result(nums.size());
        while(a <= b)
        {
            if(nums[a]*nums[a] > nums[b]*nums[b])
            {
                result[k] = nums[a]*nums[a];
                a++;
            }
            else
            {
                result[k] = nums[b]*nums[b];
                b--;
            }
            k--;    
        }
        return result;
    }
};

思考:下列算法有哪些问题?

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int a, b, k;
        a = 0;
        b = nums.size()-1;
        k = nums.size()-1;
        vector<int> result;
        while(a < b)
        {
            int A = nums[a]*nums[a];
            int B = nums[b]*nums[b];
            if(A > B)
            {
                result[k] = A;
                a++;
                k--;
            }
            else
            {
                result[k] = B;
                b--;
                k--;
            }
        }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值