zoukankan      html  css  js  c++  java
  • ACWING基础算法(三)

      双指针算法。

      相向双指针,指的是在算法的一开始,两根指针分别位于数组/字符串的两端,并相向行走。

      ACWING 的一道裸题(不知道为啥进不去404):最长连续不重复子序列

      输入

      5

      1 2 2 3 5 

      输出

      3

        需要两个指针,指针范围为不重复自序列,i,j为其两端。j为左边,i为右边。a【】数组记录原数组,s【】数组记录数字出现次数。怎么搞呢,举个例子,对于样例1 :

      1   2  2  3  5

      0      1       2  3     4

      首先j=0,i=0。。如果当前没有出现某个数的出现次数>1,那么i++,j不变。当 j=0,i=2时,出现了s[2]>1,2出现了2次,很明显不符题意了。那么需要移动指针了。根据常识,我们需要从当前出现两次的数重新开始计了,即 从i=2,j=2开始,我们可以看到,i没变,j移动了,总结:出现次数大于1的数,i不变,j右移,直到i==j。但是既然要重新计,那么记录次数的s[]数组肯定要清一下,所以s[a[j]]--,在j右移的过程中逐步清掉s[]数组,由于出了s[i]==2以外s[j]==1,所以可以把他们都清为s[a[j]]==0,而顺便把重复数s[a[ i ]]==1,重新开始计。

      有点啰嗦了,代码:

      

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn =  1e5;
    int a[maxn],s[maxn];
    int main()
    {
        int n;
        cin>>n;
        for(int i = 0 ;i < n ;i++)
            cin>>a[i];
        int maxx=-1 ;
        for(int i= 0 ,j=0;i< n;i++)
        {
            s[a[i]]++;
            while(s[a[i]]>1)
            {
                s[a[j]]--;
                j++;
            }
            maxx=max(i-j+1,maxx);
        }
        cout<<maxx<<endl;                
    }                    

       ACWING800

      给定两个升序排序的有序数组A和B,以及一个目标值x。数组下标从0开始。请你求出满足A[i] + B[j] = x的数对(i, j)。

         本来写了一个双指针,结果超时了,j每次清0的操作实在花了好多无用功。因为题目中给的两个数组,均为升序排列。所以,用 i  代表a[]数组,j 为b[]数组。j从右往左滑,i往右划。

    由于是升序排列,所以j并不需要清成m-1,因为比如:i 在 1位置+j在2位置 ==x,那么下一次 i 右移,j不会再往右移,如果往右移接下来的a+b一定>x,没必要再算了。j不能从左往右滑,不再解释,还是因为升序数组。

      

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn =  1e5+10;
    int a[maxn],b[maxn];//     
    int main()
    {
        int n ,m ,x;
        cin>>n>>m>>x;
        for(int i= 0 ;i < n ; i++)
             cin>>a[i];
        for(int i = 0 ;i< m; i++)
            cin>>b[i];
        int ans=0;
        for(int i = 0 ,j = m-1 ; i < n && j>=0;    i++)
        {    
            while(a[i]+b[j]>x&&j>=0)
            {
                j--;         
            }
            if(a[i]+b[j]==x) 
                cout<<i<<" "<<j<<endl; 
        }
    }                    

        位运算 : 

        1:  n的二进制表示中第k位是几?  n > > k & 1

        模板:表示N的二进制

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn =  1e5+10;
    int a[maxn],b[maxn];//     
    int main()
    {
         int n;
         while(cin>>n)
         {
             for(int k=9 ;k>=0; k-- )
                 cout<<(n>>k&1);
                 cout<<endl;
        }
    }                    

        2: 返回x(二进制)的最后一位1的位置

        x & (-x)==x & (x取反+1)

        ACWING

        二进制中1的个数

        

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn =  1e5+10;
    int a[maxn],b[maxn];//     
    int lowbit(int a)
    {
        return a&(-a);
    }
    int main()
    {
         int n;
         cin>>n;
         for(int i=1;i<=n;i++)
         {
             int x;
             int ans=0;
             cin>>x;
             while(x)
             {
                 ans++;
                 x-=lowbit(x);  //每次减去x的最后一位
            }
            cout<<ans<<' ';
         }    
    }                    

       离散化:整数离散化:

        要点:  1:重复元素的去重。2:如何算离散化值   

      //排序加去重

    void quchong()
    {
        vector<int>alls;    //存储所有待离散化的值
        sort(alls.begin(),alls.end());    //将所有值排序
        alls.erase(unique(alls.begin(),alls.end()),alls.end());    //去掉重复元素 
    }
    //二分法求出x对应的离散化的值 
    int find(int x)    //找到第一个大于等于x的位置
    {
        int l = 0 , r= alls.size()-1;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(alls[mid]>=x)
                r=mid;
            else
                l=mid+1;    
        }    
        return r;  //映射 
    } 

      ACWING  区间和

          10^9,不能用前缀和了。分析一下,n+2*m个坐标==3*10^5,用得着的也就这么些坐标了,其他的没必要看,所以可以用离散化来做。

      ACWING 区间合并

      vector的不会做,自己写的代码

    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int maxn = 1e5+10;
    struct node
    {
        int l,r;
    }st[maxn];
    bool cmp(node a,node b)
    {
        return a.l<b.l;
    }
    int main()
    {
        int n ; 
        cin>>n;
        for(int i= 0 ; i < n; i++)
        {
            cin>>st[i].l>>st[i].r;
        }
        sort(st,st+n,cmp);
        int sum = 1 ;
        for(int i= 0;i < n ;i++)
        {
            if(st[i].r<st[i+1].l)
            {
                sum++;
            //    cout<<st[i].l<<"  "<<st[i].r<<" -"<<st[i+1].l<<" "<<st[i+1].r<<endl;
            }
            else
            {
                if(st[i].r>st[i+1].r)
                {
                    st[i+1].r=st[i].r;
                }
            }
        }
        cout<<sum<<endl;
    }
  • 相关阅读:
    Scrapy-02-item管道、shell、选择器
    django类视图的装饰器验证
    django禁用csrf
    django admin
    关系型数据库与非关系型数据库
    LINQ.CS
    测试
    测试
    一个测试
    WPF中的Style
  • 原文地址:https://www.cnblogs.com/liyexin/p/11914047.html
Copyright © 2011-2022 走看看