蓝桥杯 800. 数组元素的目标和 知识点:双指针

87 阅读1分钟

800. 数组元素的目标和 - AcWing题库

刚开始写暴力过不了,因为两层循环,O(n2)O(n^2),题目的最大范围是1e5:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int main()
{
    int n,m,x;cin>>n>>m>>x;
    for(int i=0;i<n;i++)cin>>a[i];
    for(int j=0;j<m;j++)cin>>b[j];
    
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(a[i]+b[j]==x)
            {
                cout<<i<<" "<<j<<endl;
            }
        }
    }
    return 0;
}

image.png

这个时候我们发现数组具有单调性,即是升序数组,那么我们可以用双指针来做,降低时间复杂度。

image.png

当a[i]+a[j]大于x的时候,j就向左移:

如下,j会一直移到下标1的位置,此时a[i]+a[j]才小于x:

image.png

此时我们让i指针向右移:

image.png

这个时候我们发现a[i]+a[j]==x了,那么就输出i,j,然后结束循环。

code

第一层循环是O(n),第二层循环因为j从m到0,所以是O(m),因为j总共就执行m次,而不是i执行好一次j就要执行m次。所以是线性的,复杂度为O(n+m),而不是O(n*m)

#include<bits/stdc++.h>
using namespace std;
int n,m,x;
const int   N=1e5+10;
int a[N],b[N];


int  main()
{
    cin>>n>>m>>x;
    for(int i=0;i<n;i++)cin>>a[i];
    for(int i=0;i<m;i++)cin>>b[i];
    
    
    for(int i=0,j=m-1;i<n;i++)
    {
        
        //如果大于那就一直左移 直到小于等于x才停止
        while(j>=0&&a[i]+b[j]>x)j--;
            
        // 这个时候判断一下    
      if(a[i]+b[j]==x)cout<<i<<" "<<j<<endl;
    }
    return 0;
}