1

题目大意:

给出一个长度不超过20的整数,问这个整数乘以2以后的数位是否为原数数位的一个排列

算法思路:

由于长度有可能达到20位,超过了long long的存储范围,所以这里采用string存储输入的整数。该题只需要解决两个问题,第一个就是如何判断2个整数的互为排列,第二个就是如何计算一个字符串与2的乘法。解决第一个问题的思路就是利用hash映射的思想,利用countOfS存储0~9数字出现的次数,在输入的时候做加法,对于输入的数字s的每一位s[i],++countOfS[s[i]-'0'],在做完乘法后得到数字r,然后对r的每一个数字r[k]做减法,--countOfS[r[k]-'0'];如果减完后出现小于0的情况就说明这两个不是互为排列并且使用isTrue记录下来。第二个问题的解决思路就是使用指针j对s从后向前扫描,并且使用carry记录上一位的进位,对于每一位数字s[j],都乘以2然后加上进位carry,(s[j]-'0')*2 + carry,该结果使用multi保存,然后计算进位multi/10,并将本位使用r保存,r += to_string(multi%10);最后根据isTrue是否为true输出YesNo,然后再输出逆置后的r即可。

注意点:

1、在进行乘法运算的时候,最高位如果有进位的话,也就是carry在退出循环后不为0得再添加到r中,测试点2和测试点7考察。

提交结果:

image.png

AC代码:

#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

int main(){
    string s;
    cin>>s;
    int countOfS[11] = {};// 统计s中每一个数字出现的次数
    for (int i = 0; i < s.size(); ++i) {
        ++countOfS[s[i]-'0'];
    }
    // 将s乘以2
    string r;
    int carry = 0;
    int multi;// 部分乘积
    for (int j = s.size()-1; j >=0 ; --j) {
        multi = (s[j]-'0')*2 + carry;
        carry = multi/10;
        r += to_string(multi%10);
    }
    // 最高位还有进位
    if(carry!=0){
        r += to_string(carry);
    }
    reverse(r.begin(),r.end());
    bool isTrue = true;
    for (int k = 0; k < r.size(); ++k) {
        --countOfS[r[k]-'0'];
        if(countOfS[r[k]-'0']<0){
            isTrue = false;
            break;
        }
    }
    if(isTrue){
        printf("Yes\n");
    } else {
        printf("No\n");
    }
    printf("%s",r.c_str());
    return 0;
}

乔梓鑫
569 声望17 粉丝

主要分享个人学习经验和心得