五位黑洞數
任意一個5位數,比如:34256,把它的各位數字打亂,重新排列,可以得到一個最大的數:65432,一個最小的數23456。
求這兩個數字的差,得:41976,把這個數字再次重複上述過程(如果不足5位,則前邊補0)。
如此往復,數字會落入某個循環圈(稱爲數字黑洞)。
比如,剛纔的數字會落入:[82962,75933,63954,61974]這個循環圈。
請編寫程序,找到5位數所有可能的循環圈,並輸出,每個循環圈佔1行。其中5位數全都相同則循環圈爲 0,這個可以不考慮。
循環圈的輸出格式仿照:
[82962,75933,63954,61974]
最簡單的思路是對所有五位數進行運算判斷,若落入黑洞,則輸出這個黑洞循環,當然還要判斷這個黑洞之前是否已經輸出。但是這並不是好的解決辦法,有很多重複運算,效率較低,怎樣降低時間開銷呢,試想一下,如果一個數經過一系列運算不會落入黑洞的話,最終一定會得到0,那麼所有計算得到的中間值也一定不會落入黑洞,因爲他們計算後也會得到0,這些數就可以不必再次計算了,因此可以開一個VIS數組用來記錄已經計算過的數,但還有一個問題,如何避免兩次落入同一個黑洞,這裏可以對VIS數組設置不同的值,第一次計算時所有中間值設爲1,第二次計算時所有中間值爲2
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int vis[100000];
int cha(int num)//計算差值
{
int a[5]={0},i=0,max,min;
while(num)
{
a[i++]=num%10;
num=num/10;
}
sort(a,a+5);
max=a[4]*10000+a[3]*1000+a[2]*100+a[1]*10+a[0];
min=a[0]*10000+a[1]*1000+a[2]*100+a[3]*10+a[4];
return max-min;
}
int main()
{
vector<int> s;
vector<int>::iterator it;
int number=0;
for(int i=10000;i<100000;i++)
if(!vis[i])
{
s.clear();
s.push_back(i);
int t=cha(i);
vis[i]=number++;
while(!vis[t])
{
s.push_back(t);
vis[t]=number;
t=cha(t);
}
if(vis[t]==number&&t)//出現循環,輸出該循環
{
it=find(s.begin(),s.end(),t);
cout<<'['<<*it;
for(it=it+1;it!=s.end();it++)
cout<<','<<*it;
cout<<']'<<endl;
}
}
return 0;
}
。
代碼如下