双指针算法

双指针算法:

例题1.最长连续不重复子序列:

给定一个长度为 n 的整数序列q,请找出最长的不包含重复的数的连续区间。

数据范围:

1<=n<=1e5;

1<=q[i]<=1e5。

思路:

枚举所有区间,c(n,2),时间复杂度为O(n^2);

使用双指针算法,先固定一个左端点i,然后另一个端点j向前扫描;

当遇到重复的数后,将i向前移动到区间内不存在重复数的位置,然后重复上述操作即可;

(当i移动完成停下后,说明q[i-1]==q[j],所以q[j]不可能与q[i]之前的数形成不重复区间);

时间复杂度为O(n)。

代码如下:
int i=0,j=0;//左右指针
st[q[i]]++;//q[i]的数量+1
while(j<n){
    //如果重复就将i往前移
    while(st[q[j]]==2){
        st[q[i]]--;
        i++;
    }
        
    res=max(res,j-i+1);
    j++; 
    st[q[j]]++;
}

例题2.数组元素的目标和:

给定两个升序排列的序列p,q,以及一个目标值x,求满足p[i]+q[j]==x的一组(i,j)。数据保证有解并且唯一解。

数据范围:

1<=p,q<=1e5;

1<=p[i],q[i]<=1e9。

思路:

指针i指向p的首项,j指向q的尾项;

如果p[i]+q[j]>x,则向前移动j,如果p[i]+p[j]<x,则向后移动i;

(当p[i]+q[j]>x时,q[j]~q[n]不可能与p[i]~q[n]组成x,所以可以舍弃掉q[j],另一种情况同理)。

代码如下:
for(int i=0,j=m-1;i<n&&j>=0;){
        if(a[i]+b[j]>t)j--;
        else if(a[i]+b[j]<t)i++;
        else if(a[i]+b[j]==t){cout<<i<<" "<<j;return 0;}
}

例题3.盛水最多的容器

给定一个整数序列,每个数都代表一个挡板,每个相邻的挡板间的距离都是1,数的大小代表挡板的高度。

找出其中的两个挡板,使得他们与x轴共同构成的容器可以容纳最多的水。

你不都倾斜容器。

思路:

假设挡板i,j,挡板高度h[i],可以把盛水的量s看作是q[j]-q[i]*max(h[i],h[j]);

初始状态i,j置于两侧;

不论移动哪一个挡板,q[j]-q[i]都会变小,要想结果可能变大,必须要尽可能使得max(h[i],h[j])变大,所以我们每次移动较矮的挡板。

代码如下:
for (int i = 0, j = height.size() - 1; i < j;) {
            res = max(res, min(height[i], height[j]) * (j - i));

            if (height[i] < height[j])i++;
            else j--;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值