一,问题描述
所谓“数字黑洞”现象,就是任意给定一个4位正整数,将组成该正整数的4个数字先按非递减顺序排序,得到一个数称为Large;再将这4个数字按非递增顺序排序,得到另一个数,称为Small。然后,将Large减去Small,得到一个新的数字。当然,其它位数的也存在着这个现象,具体可参考:数字黑洞
将这个新的数字重复上面的处理,很快就会停在有“数字黑洞”之称的 6174 这个数上。这个数也称为Kaprekar常数。
二,举例说明
比如,输入6767,其演示结果如下:
7766 - 6677 = 1089
9810 - 0189 = 9621 ----将新得到的数 1089 进行非递减及 非递增排序后,分别得到 9810 和 0189(189)
9621 - 1269 = 8352
8532 - 2358 = 6174
三,核心思路分析
这个问题的核心过程是:将数字分解成各个位,然后按非递增或非递减排序,再得到排序后的数字。
数字分解的话,可以用求余 和 除法。排序的话,可以用Arrays.sort(int[] arr)。得到排序后的数字,其实就是Horner法则。
①数字分解:
private static int[] split(int n){
//assert n >= 1000; assert n <= 9999 int[] arr = new int[4]; int index = 0; while(n != 0) { arr[index++] = n % 10; n = n / 10; } return arr; }
②Horner法则得到数字:关于Horner法则可参考:求幂运算、多项式乘法及Horner法则的应用
//1089-->9810, arr是从小到大的有序数组 private static int toLarge(int[] arr){ int result = 0; for(int i = arr.length - 1; i >=0; i--) { result = result*10 + arr[i]; } return result; } //1089 --> 189 arr是从小到大的有序数组 private static int toSmall(int[] arr){ int result = 0; for(int i = 0; i < arr.length; i++) { result = result*10 + arr[i]; } return result; }
四,整个代码完整实现:
import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNextInt()) {//注意while处理多个case int number = in.nextInt(); int[] arr = split(number); if(check(arr)) { System.out.println(number + " - " + number + " = " + "0000"); } else { int res = process(number); while(res != 6174) { res = process(res); } } } } public static int[] split(int n){ int[] arr = new int[4]; int index = 0; while(n != 0) { arr[index++] = n % 10; n = n / 10; } return arr; } public static void sort(int[] arr){ Arrays.sort(arr); } public static int toLarge(int[] arr){ int result = 0; for(int i = arr.length - 1; i >=0; i--) { result = result*10 + arr[i]; } return result; } public static int toSmall(int[] arr){ int result = 0; for(int i = 0; i < arr.length; i++) { result = result*10 + arr[i]; } return result; } public static int process(int n){ int[] arr = split(n); Arrays.sort(arr); int large = toLarge(arr); int small = toSmall(arr); print(large, small, arr); return large - small; } public static void print(int large, int small, int[] arr){ System.out.println(large + " - " + arr[0] + arr[1] + arr[2] + arr[3] + " = " + (large - small)); } public static boolean check(int[] arr){ int tmp = arr[0]; for(int i = 1; i < arr.length; i++) if(arr[i] != tmp) return false; return true; } }