这篇文章讲述的是算法趣味整数部分的黑洞数问题的java实现,参考的书籍为清华大学出版社出版,贾蓓等编著的《c语言趣味编程1000例》,如有错误或者不当之处,还望各位大神批评指正。
问题描述
编程求出三位数的“黑洞数”,黑洞数又称陷阱数,任何一个数字不完全相同的整数,经有限次“重排求差”操作,总会得到一个或一些数,这些数即为黑洞数。“重排求差”操作是将组成一个数的各位数字重排得到的最大数减去最小数,例如207操作序列是
702-027=675
963-369=994
954-459=495
再做下去就不变了,再用其他三位数验证也停止到了495,所以495是三位数的黑洞数
算法分析
根据题意操作步骤如下:
1. 将一个三位数拆分
2. 排列出最大数与最小数
3. 做差值,记录
4. 再找一个数进行如上操作
5. 判断运算结果是否与上一次相同若相同则输出
代码实现
package funnyInteger;
/**
* @author 叶清逸
* @date 2018年7月14日上午11:38:12
* @version 1.0
* @project funnyInteger
*/
public class Q8_BlackHoleNumber {
/**
* 问题描述:编程求出三位数的“黑洞数”,黑洞数又称陷阱数,任何一个数字不完全相同的整数,经有限次“重排求差”操作,总会得到一个
* 或一些数,这些数即为黑洞数。“重排求差”操作是将组成一个数的各位数字重排得到的最大数减去最小数,例如207操作序列是
* 702-027=675
* 963-369=994
* 954-459=495
* 再做下去就不变了,再用其他三位数验证也停止到了495,所以495是三位数的黑洞数
*
* 算法分析:根据题意操作步骤如下:
* 1. 将一个三位数拆分
* 2. 排列出最大数与最小数
* 3. 做差值,记录
* 4. 再找一个数进行如上操作
* 5. 判断运算结果是否与上一次相同若相同则输出
*/
public static void main(String[] args) {
/*找出一个三位数*/
int num1 = 207 ;
/*重排求差*/
int first = rank(num1) ;
/*再找个同位数排列求差*/
int num2 = 208 ;
int second = rank(num2) ;
/*判断是否为黑洞数*/
if(first == second)
System.out.println(3+"位数的黑洞数为:"+first);
}
private static int rank(int number){
int last = -1 ;
/*将这个三位数分解*/
int hundred = (number%1000)/100 ;
int ten = (number%100)/10 ;
int one = (number%10) ;
int max = getMax(hundred , ten , one) ;
int min = getMin(hundred , ten , one) ;
int result = max - min ;
/*循环求差值,直到差值与上次计算时相同*/
while(result != last){
last = result ;
number = result ;
hundred = (number%1000)/100 ;
ten = (number%100)/10 ;
one = (number%10) ;
max = getMax(hundred , ten , one) ;
min = getMin(hundred , ten , one) ;
result = max - min ;
}
return result ;
}
/*获取排列最大值*/
private static int getMax(int hundred , int ten , int one){
int result = 0 ;
if(hundred < ten){
int t = hundred ;
hundred = ten ;
ten = t ;
}
if(hundred < one){
int t = hundred ;
hundred = one ;
one = t ;
}
if(ten < one){
int t = ten ;
ten = one ;
one = t ;
}
result = hundred*100 + ten*10 + one ;
return result ;
}
/*获取排列最小值*/
private static int getMin(int hundred , int ten , int one){
int result = 0 ;
if(hundred > ten){
int t = hundred ;
hundred = ten ;
ten = t ;
}
if(hundred > one){
int t = hundred ;
hundred = one ;
one = t ;
}
if(ten > one){
int t = ten ;
ten = one ;
one = t ;
}
result = hundred*100 + ten*10 + one ;
return result ;
}
}
- 问题拓展,求任意位的黑洞数
package funnyInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author 叶清逸
* @date 2018年7月14日上午11:38:12
* @version 1.0
* @project funnyInteger
*/
public class Q8_BlackHoleNumber {
/**
* 问题描述:编程求出三位数的“黑洞数”,黑洞数又称陷阱数,任何一个数字不完全相同的整数,经有限次“重排求差”操作,总会得到一个
* 或一些数,这些数即为黑洞数。“重排求差”操作是将组成一个数的各位数字重排得到的最大数减去最小数,例如207操作序列是
* 702-027=675
* 963-369=994
* 954-459=495
* 再做下去就不变了,再用其他三位数验证也停止到了495,所以495是三位数的黑洞数
*
* 算法分析:根据题意操作步骤如下:
* 1. 将一个任意位数拆分
* 2. 排列出最大数与最小数
* 3. 做差值,记录
* 4. 再找一个数进行如上操作
* 5. 判断运算结果是否与上一次相同若相同则输出
*/
public static void main(String[] args) {
/*找出一个数*/
int num1 = 1024 ;
/*重排求差*/
int first = rank(num1) ;
/*再找个同位数排列求差*/
int num2 = 1024 ;
int second = rank(num2) ;
/*判断是否为黑洞数*/
if(first == second)
System.out.println(getLength(num1)+"位数的黑洞数为:"+first);
}
/*排列求差*/
private static int rank(int number){
int last = -1 ; //存放上一次的运算结果
/*排列求出这三位数组合的最大数与最小数*/
int max = getMax(number) ;
int min = getMin(number) ;
int result = max - min ;
while(result != last){
last = result ;
number = result ;
max = getMax(number) ;
min = getMin(number) ;
result = max - min ;
}
return result ;
}
/*排列取得最大数*/
private static int getMax(int number){
int max = 0 ;
/*使用数组来存放分解后的结果*/
int arr[] = numToArr(number) ;
/*求number的长度*/
int length = arr.length ;
/*从大到小排序*/
Arrays.sort(arr);
/*计算底数用于计算最小数*/
int a = 1 ;
for(int j=1 ; j<length ; j++)
a *= 10 ;
/*将数组组成最小数*/
for(int k=length-1 ; k>=0 ;k--){
max += arr[k]*a ;
a /= 10 ;
}
return max ;
}
/*排列取得最小数*/
private static int getMin(int number){
int min = 0 ;
/*使用数组来存放分解后的结果*/
int arr[] = numToArr(number) ;
/*求number的长度*/
int length = arr.length ;
/*从大到小排序*/
Arrays.sort(arr);
/*计算底数用于计算最小数*/
int a = 1 ;
for(int j=1 ; j<length ; j++)
a *= 10 ;
/*将数组组成最小数*/
for(int k=0 ; k<length ;k++){
min += arr[k]*a ;
a /= 10 ;
}
return min ;
}
/*求参数number的长度*/
private static int getLength(Integer number){
int length = 1 ;
while(number/10>0){
length++ ;
number /= 10 ;
}
return length ;
}
/*将数字的每一位拆分后存入数组中*/
private static int [] numToArr(int num){
/*获取数字的长度*/
int length = getLength(num) ;
/*初始化存放结果的数组*/
int arr[] = new int [length] ;
/*计算底数用于取出每一位的数*/
int a = 1 ;
for(int j=0 ; j<length ; j++)
a *= 10 ;
int i = 0 ; //存放索引
while(a/10 > 0){
arr[i] = (num%a)/(a/10) ;
a /= 10 ;
i++ ;
}
return arr ;
}
}
样例输出
3位数的黑洞数为:495