ZZULIOJ 1204: 剔除相关数

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 函数返回成功读入的数据项数,读入数据时遇到了“文件结束”则返回EOFscanf ( "%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 即为真
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值