【每天一道算法题】整数循环节之和——数字黑洞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; }