1204: 剔除相关数
时间限制: 1 Sec 内存限制: 128 MB
提交: 942 解决: 348
题目描述
一个数与另一个数如果含有相同数字和个数的字符,则称两数相关。现有一堆乱七八糟的整数,里面可能充满了彼此相关的数,请你用一下手段,自动地将其剔除。
输入
多实例测试。每组数据包含一个n(n<1000),和n个int范围内的正整数。若n为0,表示结束。
输出
按从小到大的顺序输出非相关数,若没有非相关数,则输出None。
样例输入 Copy
8
213 667 3 213 43 34 677 2
3
322 232 232
0
样例输出 Copy
2 3 667 677
None
代码注释版本1
#include<stdio.h>
#include<algorithm>
using namespace std;
int relaPairs(int num1, int num2);
int main(){
int n;
int len = 0;
int arr[1010];
while (~scanf("%d", &n) && n != 0){
/*
如果遇到错误或遇到end of file,返回值为EOF。
end of file为Ctrl+z 或者Ctrl+d。
其中EOF的值为-1
(-1的补码表示全是1,按位取反后全是0,即为假)
*/
// 输入 n 个数
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
sort(arr, arr + n); // 排序 n 个数
int flagRela = 0;
for (int i = 0; i < n; i++){
flagRela = 0;
for (int j = i + 1; j < n; j++)
if (relaPairs(arr[i], arr[j]) == 1){ // 是相关数,就把后一个数 即 arr[j] 的值置为 -1(方便后续过滤,不输出)
arr[j] = -1, flagRela = 1;
}
if (flagRela == 1) // 是相关数的两个数都要删除
arr[i] = -1;
}
int flagAmount = 1; // 是否有可输出的值,
for (int i = 0; i < n; i++)
if (arr[i] != -1)
printf("%d ", arr[i]), flagAmount = 1;
if (flagAmount == 0)printf("None");
printf("\n");
}
return 0;
}
// 比较是否为相关数,是就返回 1
int relaPairs(int num1, int num2){
int m[1010] = { 0 };
int n[1010] = { 0 };
int len1 = 0, len2 = 0, maxDigit1 = -1, maxDigit2 = -1;
while (num1){
if (num1 % 10 > maxDigit1)
maxDigit1 = num1 % 10; // 统计每个数中含有的最大数字
m[num1 % 10]++; // 得到的每一位作为下标,对该下标对应的值 加 1
num1 /= 10; // 去掉当前最后一位, prepare for next circulation
}
while (num2){
if (num2 % 10 > maxDigit2)
maxDigit2 = num2 % 10;
n[num2 % 10]++;
num2 /= 10;
}
if (maxDigit1 != maxDigit2)return 0; // 两个相关数,包含的最大数字应该相同
else {
for (int i = 0; i <= maxDigit1; i++)
if (m[i] != n[i])return 0; // 对应包含的每一个数字的个数都应该是是相同的
}
return 1;
}
代码版本&注释2
// 一个数与另一个数如果含有相同数字和个数的字符,则称两数相关。
// 即都是由相同的几种数字组成,且二者使用的每一种数字的次数也是一样的。
// (自然二者一定是相同位数的数)
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cstring>
#include<string>
#include<map>
using namespace std;
map <string,int>mapStrInt;//map是以string为索引值,int为value的map,并命名为mp
vector<string>numsInput;
// numsInput 备份了所有输入
// numsOutput 储存符合要求的数(不含相关数)
string sortDigiInStr(string &str);
int main()
{
int n;
string str;
while(scanf("%d",&n),n!=0)
{
mapStrInt.clear();
for(int i = 0; i < n; i++)
{
cin >> str;
numsInput.push_back(str); // 输入值都保存到 numsInput 中
string numStrSorted = sortDigiInStr(str); // 对 str 处理后的结果 给 numStrSorted
mapStrInt[numStrSorted]++; // 对应的 numStrSorted 键的值增加一
}
vector<string>numsOutput;
for(int i = 0; i < n; i++)
{
if(mapStrInt[sortDigiInStr(numsInput[i])]==1) // 等于1说明不存在相关数,只有一个
numsOutput.push_back(numsInput[i]);
/*
n个数作为string输入,处理后保存在map中,
相关数的处理后,得到的string是一样的(数字种类和对应的个数是一样的),则map中的second值(该string对应的键值会增加 1)
*/
}
// 准备输出(先对数排序)
sort(numsOutput.begin(),numsOutput.end());//排序
int len = numsOutput.size();
if(len==0)
cout << "None" << endl;
else
{
cout << numsOutput[0]; // // 第一个前面没有空格
for(int i = 1; i < len; i++)
cout << " " << numsOutput[i];
cout << endl;
}
numsOutput.clear();//清空值
numsInput.clear();
}
return 0;
}
string sortDigiInStr(string &str) // 对str中的数字排序
{
string res = str;
sort(res.begin(),res.end());
return res;
}
知识点
~scanf
~scanf
scanf 函数返回成功读入的数据项数,读入数据时遇到了“文件结束”则返回EOF。
scanf ( "%d %d" ,&a,&b);
函数返回值为 int 型。如果a和b都被成功读入,那么 scanf 的返回值就是2;
如果只有a被成功读入,返回值为1;
如果a和b都未被成功读入,返回值为0;
如果遇到错误或遇到end of file,返回值为EOF。
end of file为Ctrl+z 或者Ctrl+d。
其中EOF的值为-1
也就是说 scanf 返回值的取值范围是大于等于-1的整数只有返回值为EOF时
其取反的的值 即 while 循环的判断条件才为0 才能结束循环
(-1的补码表示全是1,按位取反后全是0,即为假)
其它输入情况下(无论是否输入成功)while 循环的判断条件为非0 即为真