7-17 出生年_关联容器

以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才遇到4个数字都不相同的年份。”也就是说,直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求,自动填充“我出生于y年,直到x岁才遇到n个数字都不相同的年份”这句话。

输入格式:

输入在一行中给出出生年份y和目标年份中不同数字的个数n,其中y在[1, 3000]之间,n可以是2、或3、或4。注意不足4位的年份要在前面补零,例如公元1年被认为是0001年,有2个不同的数字0和1。

输出格式:

根据输入,输出x和能达到要求的年份。数字间以1个空格分隔,行首尾不得有多余空格。年份要按4位输出。注意:所谓“n个数字都不相同”是指不同的数字正好是n个。如“2013”被视为满足“4位数字都不同”的条件,但不被视为满足2位或3位数字不同的条件。

输入样例1:

1988 4

输出样例1:

25 2013

输入样例2:

1 2

输出样例2:

0 0001

实现代码:

分析:对于从 y 开始一直到 3012(因为就算最大值 3000,一直检验到 3012 也满足题意了,后面的就没必要了去判断了),将它的每一位的数字放入集合 s 里面,因为集合是不允许重 复数字的,所以集合 s 的大小就是当前这个数字的不重复数字的个数,当集合 s 的大小和 n 相等时,说明满足题意,输出就好啦!

#include<iostream>
#include<set>
using namespace std;
int main()
{
    int y,n;
    cin>>y>>n;
    for(int i=y;i<=3012;i++){
        set<int>s;
        int num=i;
        for(int j=0;j<4;j++){
            s.insert(num%10);
            num/=10;
        }
        if(s.size()==n){
            printf("%d %04d",i-y,i);
            break;
        }
    }
    return 0;
}

知识点:

set:

一、set 的概念

set 的含义是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就像一个集合一样。所有的操作的都是严格在logn时间之内完成,效率非常高。set 和 multiset 的区别是:set 插入的元素不能相同,但是 multiset 可以相同。其特点如下:

  1. 每个元素的键值都唯一,不允许两个元素有相同的键值。
  2. 所有元素都会根据元素的键值自动排序(默认从小到大)。
  3. set 中的元素不像 map 那样可以同时拥有实值(value)和键值(key),只能存储键,是单纯的键的集合。
  4. set 中元素的值不能直接被改变。
  5. set 支持大部分的map的操作,但是 set 不支持下标的操作,而且没有定义mapped_type类型。

二、set 的基本操作

使用STL标准库的 set 时,应包含头文件:#include <set>

1、set 的定义及初始化

set<Type> s						      //定义一个set容器
set<Type> s(s1)			              //定义一个set容器,并用容器s1来初始化
set<Type> s(b, e)					  //b和e分别为迭代器的开始和结束的标记
set<Type> s(s1.begin(), s1.begin()+3) //用容器s1的第0个到第2个值初始化s
set<Type> s(a, a + 5)      		      //将a数组的元素初始化vec向量,不包括a[4]
set<Type> s(&a[1], &a[4]) 			  //将a[1]~a[4]范围内的元素作为s的初始值

2、set 的基本操作

s.begin()					//返回指向第一个元素的迭代器
s.end()						//返回指向最后一个元素的迭代器
s.clear()					//清除所有元素
s.count()					//返回某个值元素的个数
s.empty()					//如果集合为空,返回true,否则返回false
s.equal_range()				//返回集合中与给定值相等的上下限的两个迭代器
s.erase()					//删除集合中的元素
s.find(k)					//返回一个指向被查找到元素的迭代器
s.insert()					//在集合中插入元素
s.lower_bound(k)			//返回一个迭代器,指向键值大于等于k的第一个元素
s.upper_bound(k)			//返回一个迭代器,指向键值大于k的第一个元素
s.max_size()				//返回集合能容纳的元素的最大限值
s.rbegin()					//返回指向集合中最后一个元素的反向迭代器
s.rend()					//返回指向集合中第一个元素的反向迭代器
s.size()					//集合中元素的数目

三、set 的用法

1、基本用法:

#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     s.insert(1);
     s.insert(2);
     s.insert(3);
     s.insert(1);
     cout<<"set的size值为 :"<<s.size()<<endl;
     cout<<"set的maxsize的值为 :"<<s.max_size()<<endl;
     cout<<"set中的第一个元素是 :"<<*s.begin()<<endl;
     cout<<"set中的最后一个元素是:"<<*s.end()<<endl;
     s.clear();
     if(s.empty())
         cout<<"set为空"<<endl;
     cout<<"set的size值为 :"<<s.size()<<endl;
     cout<<"set的maxsize的值为 :"<<s.max_size()<<endl;
     return 0;
}

输出结果:

7-17 出生年_关联容器_02

总结:

  1. 插入3之后虽然插入了一个1,但set中最后一个值仍然是3 。一共插入了4个数,但是集合中只有3个数并且是有序的,说明了set集合的两个特点,有序和不重复。
  2. begin() 和 end()函数是不检查set是否为空的,使用前最好使用empty()检验一下set是否为空。

2、count() 的用法

//返回某个值元素的个数
#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     s.insert(1);
     s.insert(2);
     s.insert(3);
     s.insert(1);
     cout<<"set 中 1 出现的次数是 :"<<s.count(1)<<endl;
     cout<<"set 中 4 出现的次数是 :"<<s.count(4)<<endl;
     return 0;
}

输出结果:

7-17 出生年_封装_03

总结: count() 用来查找set中某个键值出现的次数,但因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了,所以这个函数在set中并不是很实用。