1007.5位数字黑洞
Description
任意一个5位数,比如:34256,把它的各位数字打乱,重新排列,可以得到一个最大的数:65432,一个最小的数23456。求这两个数字的差,得:41976,把这个数字再次重复上述过程(如果不足5位,则前边补0)。如此往复,数字会落入某个循环圈(称为数字黑洞)。
比如,刚才的数字会落入:[82962, 75933, 63954, 61974] 这个循环圈。
请编写程序,找到5位数所有可能的循环圈,并输出,每个循环圈占1行。其中5位数全都相同则循环圈为 [0],这个可以不考虑。循环圈的输出格式仿照:
[82962, 75933, 63954, 61974]
其中数字的先后顺序可以不考虑。
Input
Output
[74943, 62964, 71973, 83952]
[63954, 61974, 82962, 75933]
[53955, 59994]
[0]
模拟上述过程即可,注意优化
import java.util.Arrays;
public class T71 {
static int[] data=new int[10000*10+1];
public static void main(String[] args) {
for (int i = 10000; i <= 100000; i++) {
if (convert(i) == 0) { //对于 XXXXX这样的数(例如33333),不用处理。
data[i] = 1; //标记出现过num
continue;
}
if (data[i] == 1){ //已出现过的数不再处理。
continue;
}
getQuan(i);
}
}
PRivate static void getQuan(int k) {
int[] arr=new int[1000];
arr[0]=k;
//主要的不同点:将每次做差得到的数依次放进数组中,然后输出圈的时候比较方便
//老师的将得到的数做数组下标,放进圈中,然后打印圈什么的有点复杂
while(data[k]!=1){
data[k]=1;
int m=convert(k);
k=m;
for (int i = 1; i < arr.length; i++) {
if(arr[i]==0){//圈中没有的数,放进圈中
arr[i]=m;
break;
}else{
if(arr[i]==m){//找到了圈,打印
System.out.print("[");
for (int j = i; j < arr.length; j++) {
if(arr[j]==0){
System.out.println("]");
return;
}
System.out.print(arr[j]);
if(arr[j+1]!=0)
System.out.print(",");
}
}
}
}
}
}
private static int convert(int n) {
int[] arr = new int[5];
for (int i = 0; i < 5; i++) {
arr[i] = n % 10;
n /= 10;
}
Arrays.sort(arr);
int max = 0;
int min = 0;
int tenN = 1;
for (int i = 0; i < 5; i++) {
min = 10 * min + arr[i];
max += tenN * arr[i];
tenN *= 10;
}
return max - min;
}
}
老师写的方法:
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
public class T7 {
static int[] visited = new int[100000]; // 放所有出现过的数
static int[] now = new int[100000]; //存放当前数变换出的所有结果
//双击查看原图到并打印第一次出现的圈
private static void printCircle(int num) {
int k = num;
while (visited[k] != 1 && now[k] != 1 ) //如果没有遇到圈(原来没有出现,且本轮也没有出现),则继续变换
{now[k] = num; //(1)标记本轮(num起点)出现过n
visited[k] = 1; //(2)标记出现过n
k = convert(k); //(3)继续变换
}
if(now[k]==num){ //本轮新出现的圈
Queue<Integer> queue = new LinkedList<Integer>(); //放环中的元素
queue.add(k); //k入队
k = convert(k);
while (k != queue.peek()) {
queue.add(k);
k = convert(k);
}
System.out.print( "[");
while( queue.size()>1) {
System.out.print( queue.poll() + ",");
}
System.out.println(queue.poll()+"]");
}
}
/**
* @param n
* @return 返回n变换后的值。
* 即各位数字打乱,重新排列,得到的最大数-最小数
*/
private static int convert(int n) {
int[] arr = new int[5];
for (int i = 0; i < 5; i++) {
arr[i] = n % 10;
n /= 10;
}
Arrays.sort(arr);
int max = 0;
int min = 0;
int tenN = 1;
for (int i = 0; i < 5; i++) {
min = 10 * min + arr[i];
max += tenN * arr[i];
tenN *= 10;
}
return max - min;
}
public static void main(String[] args) {
for (int num = 10000; num < 100000; num++) { //穷举五位数
if (convert(num) == 0) { //对于 XXXXX这样的数(例如33333),不用处理。
visited[num] = 1; //标记出现过num
continue;
}
if (visited[num] == 1) //已出现过的数不再处理。
continue;
printCircle(num); //输出圈(只输出第一次出现的情况)
}
}
}