Set Similarity (25)

本文档详细介绍了如何使用C++解决一个算法问题,涉及集合相似度计算。首先,分析了输入输出需求,接着设计了数据结构和算法流程,包括输入集合、计算相似度和输出结果的模块。在详细设计部分,提出了使用set数据结构存储集合,并通过迭代查找计算两个集合的交集元素,从而得出相似度。最后,提供了完整的C++代码实现,并强调了在编写算法时要注意的效率问题。
摘要由CSDN通过智能技术生成

前言

《算法笔记》 set的常见用法


一、题目描述

题目见:http://codeup.hustoj.com/problem.php?cid=100000597&pid=0
题意:两个整数集合的相似度定义为两集合中相同的元素个数除以总共的元素个数(不重复),任务是求任意两个集合的相似度。

二、需求分析

1.输入分析

每个输入文件一个测试用例。
第一行输入一个正整数N(<=50),接下来输入N个集合,一个集合占一行,且首先给出集合元素个数 M(<104),再给出M个元素。然后一行输入一个正整数K(<=2000),后面输入K行成对的数据,表示需要查询的两个集合(编号从1到2500)。

2.输出分析

对每个查询,以保留一位小数的百分数形式输出集合的相似度,占一行。

3.功能分析

(1)输入集合
(2)求两个集合间的相似度
(3)输出集合的相似度

4.测试数据

输入:

3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3

输出:

50.0%
33.3%

三、概要设计

1.数据结构

集合使用set来保存即可。

2.基本操作

基本操作操作结果
get_set()输入集合
calculate_similarity()计算两个集合间的相似度
print_similarity()输出要查询的相似度

3.模块及调用图

(1)集合输入模块get_set()
(2)相似度计算模块calculate_similarity()
(3)相似度输出模块print_similarity()
(4)主模块main()
模块调用图:
在这里插入图片描述

四、详细设计

1.数据结构

所有集合的保存,使用set数组,大小定义为50。
相似度的保存,使用一维数组保存,数据类型为double,大小定义为2000。

2.各模块

(1)集合输入模块
输入数据规模N,获取N个集合。
(2)相似度计算模块
输入K对整数,计算相应集合的相似度。设两个集合S1、S2,其相似度计算算法如下:
① 思路1,将两个集合合并成一个集合,进行相似度的计算,但是提交的时候错误,百度发现这种方法超时。
② 思路2,在一个集合中查询另一个集合中的元素,计算相同元素的个数。set.find()的返回值是一个迭代器,没找到值为set.end(),遍历完了也没有找到。
实际计算中注意数据类型转换。
(3)相似度输出模块
将相似度按格式输出,“%.1f%%\n”。

五、代码编写

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

using namespace std;

const int maxn=60;
const int maxq=2000;
set<int> sets[maxn];
double similarity[maxq];


void get_set(){
    int N;
    int n,num;

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

int caculate_similarity(){
    int K;
    int s1,s2;
    int Nc,Nt;
    set<int> temp_set;
    set<int>::iterator it;

    scanf("%d",&K);
    for(int i=0;i<K;i++){
        scanf("%d%d",&s1,&s2);
        Nc=0;
        for(it=sets[s1-1].begin();it!=sets[s1-1].end();it++)
           if(sets[s2-1].find(*it)!=sets[s2-1].end()) Nc++;
        Nt=sets[s1-1].size()+sets[s2-1].size()-Nc;

        similarity[i]=Nc*1.0*100/Nt;
    }
    return K;
}

void print_similarity(int n){
    for(int i=0;i<n;i++) printf("%.1f%%\n",similarity[i]);
}


int main(){
    int n;
    get_set();
    n=caculate_similarity();
    print_similarity(n);
    return 0;
}

六、总结

  1. 百分号的输出前面要再加一个百分号,printf("%%");
  2. set的find()方法返回的是一个迭代器,找到的话是指向这个元素的迭代器,没找到指向集合的结束位置及set.end()
  3. 在编写算法时,尽量使用复杂度低的方法。查找find()的复杂度肯定要比插入insert()的复杂度要低,因为插入也要判断元素是否在不在集合内,即也要进行查找。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值