【每天一道算法题】整数循环节之和——数字黑洞6174

 

华为优招第三题,前两道题都比较简单,在这道题上卡住了。说实话不怪我,华为这道题描述有问题哦。其实不应该是较大的数,和较小的数。是最大的数和最小的数。(我在随机举例可能的数字组合上浪费了很多时间!!怒!)

整数之循环节点求和
描述: 
任意一个不是用完全相同数字组成的四位数,如果对它们的每位数字重新排序,组成一个较大的数和一个较小的数,然后用较大数减去较小数,差不够四位数时在前面补零,类推下去,最后将变成一个固定的数:6174。
例如:4321-1234=3087   8730-378=8352   8532-2358=6174   7641-1467=6147。  
如果K位数也照此办理,它们不是变成一个数,而是在几个数字之间形成循环,例如对于五位数54321: 54321-12345=41976  97641-14679=82962   98622-22689=75933     97533-33579=63954   96543-34569=61974   97641-14679=82962    
我们把82962  75933  63954  61974称作循环节。在前面6174中,循环节认为只有一个数。
请输出这些循环节之和,最终结果可能需要使用64位的整型才能存放。当没有循环节,输出0,例如:输入33333,输出0。
运行时间限制: 无限制
内存限制:   无限制
输入: 
输入为一个正整数,取值范围位0~0xffffffff
输出: 
输出为各循环节的和
样例输入:   
3214
样例输出:   
6174

那其实用递归就可以解决了。

1.拆分每一位的数到vector

2.vector排序得到最大的数、最小的数

3.递归(出口条件,差值重复出现)

代码。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void cyclesum(int num,vector<int>& dis){
    int size=0;
    vector<int> digits;
    while (num!=0){
        digits.push_back(num%10);
        size++;
        num/=10;
    }
    sort(digits.begin(),digits.end());
    int maxnum=0,minnum=0;
    for(int i=0;i<size;i++){
        minnum=minnum*10+digits[i];
        maxnum=maxnum*10+digits[size-i-1];
    }
    int result=maxnum-minnum;
    if(result==0){
        cout<<"0"<<endl;
        return;
    }
    if(find(dis.begin(),dis.end(),result)==dis.end()){
        dis.push_back(result);
        return cyclesum(result,dis);
    }
    else{
        auto j=find(dis.begin(),dis.end(),result);
        long ret=0;
        for(;j!=dis.end();j++)
            ret+=*j;
        cout<<ret<<endl;
        return;
    }
}
int main(){
    int num=0;
    cin>>num;
    
    if(num==0)
        cout<<"0"<<endl;
    vector<int> dis;
    cyclesum(num,dis);
    return 0;
}

 

posted @ 2016-08-14 19:45  0giant  阅读(2506)  评论(0编辑  收藏  举报