您的位置:首页 > 其它

PAT-A 1063. Set Similarity (25)

2018-01-15 19:35 337 查看
一道STL(set)的练习题。

set翻译为集合,是一个内部自动有序不含重复元素的容器,这是set非常重要的特性,要在实际问题中充分利用之。

除此之外,值得注意的是,set的基本操作:insert()、find()等一些操作的时间复杂度为O(logN)。

题目链接在此

题意

给出N个集合,然后有K个查询,给出每个查询的Set Similarity,即(Nc/Nt)*100.0。Nc为两个集合的交集的元素个数,Nt为两个集合的并集的元素个数。

思路及实现

刚开始有两种想法:

想法一:对于交集,自己实现一个求交集的函数,时间复杂度到了O(N^2);对于并集,则利用set的特性,将两个集合放到一个set中,即可得到并集。

想法二:直接利用< algorithm >头文件中的set_union()、set_intersection()求得并集和交集

实践证明,以上两种方法都会有一组测试点超时。

那么如何降低求交集和并集的时间复杂度呢?想想上面提到的set的find()操作,它的时间复杂度达到了O(logN)。

以下是程序的正确思路,时间复杂度为O(NlogN):

用一个set数组sets保存所有输入的集合

要查询的两个集合分别为sets[a]、sets[b]

初始化Nc=0, Nt=sets[b].size()(集合b的元素个数)

然后一边遍历集合a,一边用find()操作在集合b中查找是否在b中也存在某元素,若存在,则Nc++,若不存在,则Nt++。最后即可求得所求比值。

#include<stdio.h>
#include<set>
#include<algorithm>

using namespace std;

const int N = 51;
set<int> sets
;

void getNcAndNt(int a, int b, int &nc, int &nt){  //求集合a与集合b的nc和nt
for(set<int>::iterator ita = sets[a-1].begin(); ita != sets[a-1].end(); ita++){
if(sets[b-1].find(*ita) != sets[b-1].end()){   //在b集合中能找到该元素
nc++;
}else{          //在b集合中不能找到该元素
nt++;
}
}
}

int main(){

int n;   // total number of set
scanf("%d",&n);

for(int i = 0; i < n; i++){     //get sets
int num;
scanf("%d", &num);

for(int j = 0; j < num; j++){
int temp;
scanf("%d", &temp);
sets[i].insert(temp);
}
}

//获取查询并求并集和交集个数
int query;
scanf("%d", &query);
for(int i = 0; i < query; i++){
int a,b;
scanf("%d %d",&a, &b);

int nc = 0,nt = sets[b-1].size();  //交集个数,并集个数
getNcAndNt(a, b, nc, nt);

printf("%.1lf%%\n", nc*100.0/nt);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: