PAT(A)- 1120. Friend Numbers (20)


Two integers are called "friend numbers" if they share the same sum of their digits, and the sum is their "friend ID". For example, 123 and 51 are friend numbers since 1+2+3 = 5+1 = 6, and 6 is their friend ID. Given some numbers, you are supposed to count the number of different friend ID's among them. Note: a number is considered a friend of itself.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N. Then N positive integers are given in the next line, separated by spaces. All the numbers are less than 104.

Output Specification:

For each case, print in the first line the number of different frind ID's among the given integers. Then in the second line, output the friend ID's in increasing order. The numbers must be separated by exactly one space and there must be no extra space at the end of the line.

Sample Input:
8
123 899 51 998 27 33 36 12
Sample Output:
4
3 6 9 26

思路分析:简单题,用了4种做法

方法一:各位求和+散列。因为题目数据范围是10000,最大的数是4 * 9 = 36。所以散列表开大37就可以了。另外要会写各位数求和的方法,得到的结果作散列标记。

#include <cstdio>

#define MAX 37      // 数据范围是10^4,最大是9999,散列表开到37就可以

int table[MAX];     // table做散列表,初始全部是0,发现朋友数相应位置标记为1
int cnt = 0;        // 全局cnt,统计所有朋友数的个数

void caculate( int num ) {
    int sum = 0;    // 各位求和
    while( num ) {
        sum = sum + num % 10;
        num = num / 10;
    }

    if( table[sum] == 1 ) return;   // 如果已经标记过直接return结束函数
    else {                          // 没有标记过,进行标记并cnt加1
        table[sum] = 1;
        cnt++;
    }
}

int main() {
    int n;
    scanf( "%d", &n );

    int num;
    for( int i = 0; i < n; i++ ) {
        scanf( "%d", &num );
        caculate( num );
    }

    printf( "%d\n", cnt );              // 先打印朋友数的个数

    bool flag = false;                  // flag控制输出格式
    for( int i = 0; i < MAX; i++ ) {
        if( table[i] == 1 ) {
            if( flag == false ) {
                printf( "%d", i );
                flag = true;
            }
            else printf( " %d", i );
        }
    }

    return 0;
}


方法二:字符串+散列表。思想和方法一是一样的,但题目数据范围较小,用int就行。但如果数据很大呢?就要用字符串读入数据了。

#include <cstdio>
#include <string.h>

#define MAX 37

int table[MAX];
int cnt = 0;

void caculate( char str[] ) {
    int sum = 0;
    for( int i = 0; i < strlen( str ); i++ ) {
        sum = sum + str[i] - '0';
    }

    if( table[sum] == 1 ) return;
    else {
        table[sum] = 1;
        cnt++;
    }
}

int main() {
    int n;
    scanf( "%d", &n );

    char num[6];

    for( int i = 0; i < n; i++ ) {
        scanf( "%s", num );
        caculate( num );
    }

    printf( "%d\n", cnt );              // 先打印朋友数的个数

    bool flag = false;                  // flag控制输出格式
    for( int i = 0; i < MAX; i++ ) {
        if( table[i] == 1 ) {
            if( flag == false ) {
                printf( "%d", i );
                flag = true;
            }
            else printf( " %d", i );
        }
    }

    return 0;
}


方法三:使用set集合存储结果。因为set的特点就是没有重复元素,而且元素是从小到大排列的,所以用set存储很方便,不用考虑去重,不用考虑排序。

#include <cstdio>
#include <set>

using namespace std;

set<int> s;

void caculate( int num ) {
    int sum = 0;    // 各位求和
    while( num ) {
        sum = sum + num % 10;
        num = num / 10;
    }

    s.insert( sum );
}

int main() {
    int n;
    scanf( "%d", &n );

    int num;
    for( int i = 0; i < n; i++ ) {
        scanf( "%d", &num );
        caculate( num );
    }

    printf( "%d\n", s.size() );

    // 使用迭代器遍历set集合
    for( set<int>::iterator it = s.begin(); it != s.end(); it++ ) {
        if( it == s.begin() ) printf( "%d", *it );
        else printf( " %d", *it );
    }

    return 0;
}


方法四:很直白的小白做法:使用数组存储,但要考虑排序和去重。这里为了体现数组去重的方法,所以写的有些繁琐,考场上不建议这么做。

#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> vec;

void caculate( int num ) {
    int sum = 0;
    while( num ) {
        sum = sum + num % 10;
        num = num / 10;
    }

    vec.push_back( sum );
}

int vecSize() {
    int cnt = 0;
    int pre = -1;
    for( int i = 0; i < vec.size(); i++ ) {
        if( vec[i] != pre ) {
            cnt++;
            pre = vec[i];
        }
    }

    return cnt;
}

int main() {
    int n;
    scanf( "%d", &n );

    int num;
    for( int i = 0; i < n; i++ ) {
        scanf( "%d", &num );
        caculate( num );
    }

    sort( vec.begin(), vec.end() );

    printf( "%d\n", vecSize() );

    bool flag = false;
    int pre = -1;
    for( int i = 0; i < vec.size(); i++ ) {
        if( vec[i] != pre ) {
            if( flag == false ) {
                printf( "%d", vec[i] );
                flag = true;
            }
            else printf( " %d", vec[i] );
            pre = vec[i];
        }
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值