废话不多说,直接上代码
package lonton.com;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
-
@author Zhou
/
public class NarcissisticNumber {
/
* 一:总体思路:先求出结果,再根据结果中数值进行比对- 1使用递归,求出0~9的n次方
- 2创建一个map集合,集合中key-value分别为09,09的n次方
- 3使用递归找到各个数字可能出现的次数,创建一个长度为10的数组,将次数根据下标放进数组
- 4获取和值,通过数组下标值与map中key值一致获取value值,乘以数组下标所对应的值
- 5比较结果的长度是否与要求的位数一致,数字个数与数组中存放的次数是否一致.
* 二:编码步骤 - 1定义一个list集合存放水仙花数
- 2定义getNarcissistic方法,将0~9的n次方的值存入map集合中
- 3.1定义一个方法getTargetNum获取目标(水仙花)
- 3.2使用递归算法获取各个数字出现的所有可能性,写出结束条件
- 3.3通过map中的value值与数组中存放相关数字的乘积求出结果
- 3.4对结果进行判断,是否为水仙花数,结果为肯定时放进list集合中
- 4利用System.currentTimeMillis()方法获取运算时间.
*/
// 创建list,用于存放水仙花数
private static List list = new ArrayList();
// 所求水仙花的位数
private static int N;
public static void main(String[] args) {
// 设置起始时间
long start = System.currentTimeMillis();
for (int n = 3; n <= 21; n++) {
getNarcissistic(n);
}
// 遍历集合,输出水仙花数
System.out.println(list.toString());
long end = System.currentTimeMillis();
Long time = end - start;
System.out.println(time);
}/**
*- @param n 所求水仙花位数
*/
private static void getNarcissistic(int n) {
N = n;
Map<Integer, BigInteger> map = new HashMap<>();
int[] arr = new int[10];
// 将i的n次方的值存入map中
for (int i = 0; i < 10; i++) {
BigInteger value = BigInteger.valueOf(i).pow(n);
map.put(i, value);
}
getTargetNum(map, 0, n, arr);
}/**
- 此方法用来获取水仙花数,并存放在list集合中
- @param map value中存放的是09数字的n次方,key为09
- @param index 表示递归现在进行到arr数组的那个元素
- @param leave 表示元素最多能够出现的次数
- @param arr 数组的下标表示0-9这10个数字,arr数组元素的值表示下标数字出现的次数
*/
private static void getTargetNum(Map<Integer, BigInteger> map, int index, int leave, int[] arr) {
// 定义一个和值,即结果值
BigInteger sum = BigInteger.ZERO;
if (index == 9) {
// 当下标为9时,说明之前的数字已经分配完毕
arr[9] = leave;
// 9的21次方出现的次数不能超过10次,因为9的21次方是21位数
if (arr[9] < arr.length) {
for (int i = 0; i < arr.length; i++) {
// 用map的value值乘以数组的值
BigInteger bigNum = map.get(i).multiply(BigInteger.valueOf(arr[i]));
sum = sum.add(bigNum);
}
// 将和值转化成字符串,获取其长度
String str = String.valueOf(sum);
// 判断字符串长度,长度相等时再进行数字判断
if (str.length() != N) {
return;
}
if (str.length() == N) {
// 给定一个数组用来存放结果中的数字个数
int[] arr1 = new int[arr.length];
for (int i = 0; i < str.length(); i++) {
arr1[str.charAt(i) - ‘0’]++;
}
// 两个数组进行比较,结果一致时说明获取的sum为水仙花数
for (int j = 0; j < arr1.length; j++) {
if (arr[j] != arr1[j]) {
return;
}
}
list.add(sum);
}
}
return;
}
for (int i = 0; i <= leave; i++) {
arr[index] = i;
getTargetNum(map, index + 1, leave - i, arr);
}
}
}