双指针刷题记录

文章介绍了使用双指针策略解决数组相关问题的几种方法,包括去除重复元素、计算容器盛水最大面积、找出数组中柱状体能容纳的水量、移动零元素以及删除连续重复数字。每种问题的解决方案都涉及对数组的遍历和更新,利用两个指针的不同移动策略来达到目标。
摘要由CSDN通过智能技术生成

26:

 解决思路:

        定义两个下标指示变量i,j;在一开始时都指向数组开头。i变量正常循环,检查当前变量与前一个是否相同,如果当前变量与前一个不同,那么给j的位置赋当前值,并将j后移一位。

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

11:

 解决思路:本题的难点在于思考方式。

设定i指向数组头,j指向数组尾,那么容器盛水的量=min(height[i], height[j])* (j-i);

1. 当height值较大的指针向内移动时,min(height[i], height[j])可能变大/不变/变小;

2. 当height值较小的指针向内移动时,min(height[i], height[j])可能变大/不变,但不可能变小;

总而言之,盛水的量取决于较小的容器。

由此写循环,当i, j两指针相遇时结束循环:循环中如果height[i]较小,那么j移动,计算当前体积并迭代,反之亦然。

class Solution {
public:
    int maxArea(vector<int>& height) {
        int size=height.size();
        int i=0,j=size-1;
        int maxsize=-1;
        while(i<j){
            if(height[i]<height[j]){
                maxsize=max(maxsize,(j-i)*height[i]);
                printf("%d,",(j-i)*height[i]);
                i+=1;
            }
            else{
                maxsize=max(maxsize,(j-i)*height[j]);
                printf("%d,",(j-i)*height[j]);
                j-=1;
            }
        }
        return maxsize;
    }
};

42:

解题思路:

本题和寻找最大矩形思想较为相似,但本体更为简单。

首先设定左右left、right两个数组,left数组记记录每个柱状体的左边界,right数组记录每个柱状体的右边界;最终每个柱状体能乘水的体积即为min(left[i], right[i])*(较小边界与当前柱体高度差)。

感觉描述不清楚,复制一位评论区dalao的话作为进一步解释:

对于vector中每个点,水有多高取决于这个点左侧和右侧墙壁的最大高度。第一个for循环找每个点的左侧最大高度,第二个for循环找每个点右侧的最大高度,循环中跳过最左侧(i=0)和最右侧点(i=vector.size()-1)的原因是这两个点由于没有左侧墙壁或右侧墙壁所以最大墙壁高度肯定是0,故在初始化vector的时候已经将其默认设置成0了。在得到所有点的左右墙壁最大高度后,木桶原理取左右墙壁较低的那个高度减去当前位置墙壁作为地面的高度就得到了这个位置上水的高度。然后将所有点的水高度相加即为解。

class Solution {
public:
    int trap(vector<int>& height) {
        int size=height.size();
        int result=0;
        vector<int> left(size,0);
        vector<int> right(size,0);

        for(int i=1;i<size;i++){
            left[i]=max(left[i-1],height[i-1]);
        }

        for(int j=size-2;j>0;j--){
            right[j]=max(right[j+1],height[j+1]);
        }

        for(int k=0;k<size;k++){
            int level=min(left[k],right[k]);
            result+=std::max(0,level-height[k]);
            // printf("左边:%d,右边:%d,当前体积:%d\n",left[k],right[k],result);
        }

        return result; 
    }
};

283:

解决方法:双指针

解决思路:设定两个指针(循环变量i和q),第一个循环变量i跟随数组完成遍历,第二个循环变量q初始处于数组头,循环开始后,如果i处数组元素不为0;那么将将i处值变为0,原本的非零值赋值给nums[q],同时q后移一位。

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

80:

解决方法:双指针

解决思路:设定两个指针i和q,i随数组进行遍历,q初始指向开头:

如果当前数字出现次数<=2,那么将当前值nums[i]赋值给nums[q],并让q后移一位;如果当前数字出现次数>2,那么直接进入下一轮循环,不赋值,q也不移动。

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        unordered_map<int,int> mp;
        int q=0;
        int size=nums.size();
        for(int i=0;i<size;i++){
            mp[nums[i]]++;
            // 特定元素出现超过两次时直接进入下一轮循环
            if(mp[nums[i]]>2){
                continue;
            }
            // q跟随i复制数组中的值
            else{
                int temp=nums[i];
                nums[i]=0;
                nums[q++]=temp;
            }
        }
        return q;
    }
};

1047:

 本道题推荐使用双指针,但我觉得栈更好用......然后直接用栈超时了。

所以用string字符串模拟栈。

class Solution {
public:
    string removeDuplicates(string s) {
        string result="";
        for(auto item:s){
            if(!result.empty()&&result.back()==item){
                result.pop_back();
            }
            else{
                result.push_back(item);
            }
        }
        return result;
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值