DHU数据结构-顺序表- ADT应用-找匹配

目录

1.题目

2.题解

3.代码实现


1.题目

顺序表ADT模板设计及简单应用:找匹配

作者: 冯向阳 时间限制: 1S 章节: DS:线性表

问题描述 :

目的:使用自行设计的顺序表ADT或STL的vector模板设计并实现顺序表应用场合的一些简单算法设计。

应用8:假设有一个整数类型的顺序表(假定为非空表),元素取值可能是1~N(10<=N<=100000)中的任意一个数,相同数值不会重复出现。试设计一个算法,用O(n)的时间复杂度将找出顺序表中符合条件的数对的个数,满足数对中两数的和等于N+1。

(1)顺序表ADT版本

参考函数原型:

         template<class ElemType>
         int getCount(SqList<ElemType> &A, int N);

(2)vector版本

参考函数原型:

         template<class ElemType>
         int getCount(vector<ElemType> &A, int N);

函数形参:

    A: 整数类型的顺序表,其元素取值可能是1~N(10<=N<=100000)中的任意一个数

    N: 在A中,查找两个数的和等于N+1的对数

函数返回值:

  返回统计结果

输入说明 :

第一行:整数N,表示给定的N值。

第二行:顺序表的数据元素(取值可为1~N中的任意一个数),以空格分隔

输出说明 :

第一行:顺序表A的遍历结果,以“,”分隔。

空行

第二行:统计结果

输入范例 :

100000
100000 99999 99998 99997 99996 99995 99994 99993 99992 99991 99990 99989 99988 99987 99986 99985 99984 99983 99982 99981 99980 99979 99978 99977 99976 99975 99974 99973 99972 99971 99970 99969 99968 99967 99966 99965 99964 99963 99962 99961 99960 99959 99958 99957 99956 99955 99954 99953 99952 99951 99950 99949 99948 99947 99946 99945 99944 99943 99942 99941 99940 99939 99938 99937 99936 99935 99934 99933 99932 99931 99930 99929 99928 99927 99926 99925 99924 99923 99922 99921 99920 99919 99918 99917 99916 99915 99914 99913 99912 99911 99910 99909 99908 99907 99906 99905 99904 99903 99902 99901 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149

输出范例 :

100000,99999,99998,99997,99996,99995,99994,99993,99992,99991,99990,99989,99988,99987,99986,99985,99984,99983,99982,99981,99980,99979,99978,99977,99976,99975,99974,99973,99972,99971,99970,99969,99968,99967,99966,99965,99964,99963,99962,99961,99960,99959,99958,99957,99956,99955,99954,99953,99952,99951,99950,99949,99948,99947,99946,99945,99944,99943,99942,99941,99940,99939,99938,99937,99936,99935,99934,99933,99932,99931,99930,99929,99928,99927,99926,99925,99924,99923,99922,99921,99920,99919,99918,99917,99916,99915,99914,99913,99912,99911,99910,99909,99908,99907,99906,99905,99904,99903,99902,99901,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149

51


2.题解

  • 读题:造表(只有int类型)+找匹配的算法
  • 造顺序表:因为只有int类型的数据,所以直接对输入数据作string转为int的操作就行
  • 找匹配:就是在一个表中找到两个数让答案为确定数。最无脑的就是枚举呗,但是不知道会不会时间太长(复杂度O(n*n) ),但是看样例给那么长 大概率不行哈,所以机智的我准备优化。我一开始想到了双指针,因为需要寻找表中的两个数,但是因为这题中并没有保证表中数据是有序排列的,所以用双指针的效果和上面的枚举是一样的(就是说双指针很适用于有顺序的容器中去找东西,比如第六题中合并有序表就是用了双指针吧时间复杂度降低了)。然后因为涉及到查值算法的优化,所以想到了哈希表,(哈希表就是一个映射关系集合,从key->value以时间复杂度为O(1)的时间查到值。相当于一个数组a={0,1},下标是key,元素是value,可以通过O(1)复杂度从下标查到元素值。)在这题中我先把哈希表打出来,把所有顺序表中的元素作为这个哈希表的key(下标),然后把哈希表的value设为是否已经查找过,查过为0,没查过为1,这样就很容易查找某个值是否有匹配顺便还去重了。有点啰嗦,直接上代码吧,代码挺容易懂的。

3.代码实现

  • 造顺序表
  • 找匹配
    template<class T>
    int getcount(vector<T> &A,int N)
    {
        print(A);
    
        vector<int> vectorhash(N);//一个空哈希表
        vectorhash.assign(N+1,0);//vector预设空间,并把这些空间都设为0
        typename std::vector<T>::iterator it=A.begin();
        while(it!=A.end())//打哈希表,把顺序表中有的元素作为哈希表的key,同时把他们的value设置为1(表示可以用于匹配)
        {
            vectorhash.at(*it)=1;
            it++;
        }
    
        int res=0;
        it=A.begin();
        while(it!=A.end())//遍历顺序表去找匹配的对数
        {
            vectorhash.at(*it)=0;//用于匹配过了或者查询过了就把元素对应的哈希表值设为0
            if(vectorhash.at(N+1-*it)==1)//查找成功
            {
                res++;//答案数量+1
                vectorhash.at(N+1-*it)=0;//匹配成功的元素对应哈希表的值置为0
            }
            it++;//继续遍历顺序表
        }
        return res;//返回答案
    }

  • 完整代码
//双指针或者模拟哈希表
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

template<class T>
void print(vector<T> &A)
{
    int i;
    for(i=0;i<A.size()-1;i++)
    {
        cout<<A[i]<<",";
    }
    cout<<A[i]<<endl;
    cout<<endl;
}
template<class T>
int getcount(vector<T> &A,int N)
{
    print(A);

    vector<int> vectorhash(N);
    vectorhash.assign(N+1,0);
    typename std::vector<T>::iterator it=A.begin();
    while(it!=A.end())
    {
        vectorhash.at(*it)=1;
        it++;
    }

    int res=0;
    it=A.begin();
    while(it!=A.end())
    {
        vectorhash.at(*it)=0;
        if(vectorhash.at(N+1-*it)==1)
        {
            res++;
            vectorhash.at(N+1-*it)=0;
        }
        it++;
    }
    return res;
}

int main()
{
    int N,num=0;
    string s;
    cin>>N;
    getchar();
    getline(cin,s);
    vector<int> a;
    for(int i=0;i<s.size();i++)
    {
        if(s[i]==' ')
        {
            a.push_back(num);
            num=0;
        }
        else
        {
            num=num*10+s[i]-'0';
        }
    }
    a.push_back(num);
    cout<<getcount(a,N)<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值