黑马程序员技术交流社区

标题: 5位黑洞数的逻辑题 [打印本页]

作者: 土菠萝    时间: 2016-5-28 17:30
标题: 5位黑洞数的逻辑题
任意一个5位数,比如:34256,把它的各位数字打乱,重新排列,可以得到一个最大的数:65432,一个最小的数23456。求这两个数字的差,得:41976,把这个数字再次重复上述过程(如果不足5位,则前边补0)。如此往复,数字会落入某个循环圈(称为数字黑洞)。
比如,刚才的数字会落入:[82962, 75933, 63954, 61974] 这个循环圈。

请编写程序,找到5位数所有可能的循环圈,并输出,每个循环圈占1行。其中5位数全都相同则循环圈为 [0],这个可以不考虑。
[53955,59994]
[61974,82962,75933,63954]
[62964,71973,83952,74943]


作者: Curvat    时间: 2016-5-28 22:24
这不是蓝桥杯的经典题目么
public class NumberBlackHole
{
        @SuppressWarnings("unchecked")
        ArrayList list = null;
        @SuppressWarnings("unchecked")
        public static void main(String[] args) throws Exception
        {
                NumberBlackHole nbh = new NumberBlackHole();
                //循环:从10000~99999的所有五位数,求出所有5位数的数字黑洞
                for(int i = 10000; i <= 99999; i++)
                {
                        //当数字可以整除11111直接输出"[0]"
                        if(i % 11111 == 0)
                        {
                                //System.out.println("[0]");
                                continue;
                        }
                        //调用方法getCycle()来得到数字序列list
                        ArrayList list2 = nbh.getCycle(i, 0);
                       
                        //标志索引:数字黑洞的开始索引。
                        int deleteIndex = 0;
                        //遍历得到的list2(数字序列)
                        for(int j = 0; j < list2.size(); j++)
                        {
                                //得到数字黑洞的开始索引
                                if(list2.get(j).equals(list2.get(j + 4)))
                                {
                                        deleteIndex = j;
                                        break;
                                }
                        }
                        //删除数字黑洞开始索引之前的数字
                        for(int k = 0; k < deleteIndex; k++)
                        {
                                list2.remove(0);
                        }
                        //删除数字黑洞之后的数字,只保留数字黑洞一次循环体
                        for(int m = 0; m < 10 - deleteIndex - 4; m++)
                        {
                                list2.remove(list2.size() - 1);
                        }
                        //打印数字黑洞的一次循环体
                        System.out.println(list2);
                }
        }
        /**
         * @param number 传过来的5位数
         * @param index 是该方法在递归的时候做标识退出
         * @return ArrayList 装有数字黑洞的数字序列
         */
        @SuppressWarnings("unchecked")
        public ArrayList getCycle(int number, int index)
        {
                //首次进入该方法,创建一个ArrayList,用于装数字序列
                if(0 == index) list = new ArrayList();
                //当递归十次,返回长度为10的数字序列list
                if(10 == index) return list;
               
                //把传过来的数字转换成String,再把String转换成char[]数组
                String str = String.valueOf(number);
                char[] chars = str.toCharArray();
                //再对数组进行升序排序,从而得到最大值和最小值
                Arrays.sort(chars);
               
                //初始化传过来的五位数字
                int first = 0;
                int second = 0;
                int three = 0;
                int four = 0;
                int five = 0;
                //当最大值-最小值得到的结果为五位数
                if(5 == chars.length)
                {
                        first = Integer.parseInt(String.valueOf(chars[0]));
                        second = Integer.parseInt(String.valueOf(chars[1]));
                        three = Integer.parseInt(String.valueOf(chars[2]));
                        four = Integer.parseInt(String.valueOf(chars[3]));
                        five = Integer.parseInt(String.valueOf(chars[4]));
                }
                //当最大值-最小值得到的结果为四位数
                else if(4 == chars.length)
                {
                        second = Integer.parseInt(String.valueOf(chars[0]));
                        three = Integer.parseInt(String.valueOf(chars[1]));
                        four = Integer.parseInt(String.valueOf(chars[2]));
                        five = Integer.parseInt(String.valueOf(chars[3]));
                }
                //当最大值-最小值得到的结果为三位数
                else if(3 == chars.length)
                {
                        three = Integer.parseInt(String.valueOf(chars[0]));
                        four = Integer.parseInt(String.valueOf(chars[1]));
                        five = Integer.parseInt(String.valueOf(chars[2]));
                }
                //当最大值-最小值得到的结果为二位数
                else if(2 == chars.length)
                {
                        four = Integer.parseInt(String.valueOf(chars[0]));
                        five = Integer.parseInt(String.valueOf(chars[1]));
                }
                //当最大值-最小值得到的结果为一位数
                else if(1 == chars.length)
                {
                        five = Integer.parseInt(String.valueOf(chars[0]));
                }
                else
                {
                        return null;
                }
                //把传过来的五位数排成最大值和最小值
                int minValue = first*10000 + second*1000 + three*100 + four*10 + five;
                int maxValue = first + second*10 + three*100 + four*1000 + five*10000;
                //得到最大值-最小值的差count
                int count = maxValue - minValue;
                //把上面得到的差count放到list当中
                list.add((Integer)count);
                //进行递归,递归结束条件由index来控制
                getCycle(count, index + 1);
                return list;
        }
}
作者: 土菠萝    时间: 2016-5-29 00:11
Curvat 发表于 2016-5-28 22:24
这不是蓝桥杯的经典题目么
public class NumberBlackHole
{

蓝桥杯是什么东西,反正我自己写出来一份,只是想参考一下其他的答案而已啦!
作者: 土菠萝    时间: 2016-5-29 00:20
Curvat 发表于 2016-5-28 22:24
这不是蓝桥杯的经典题目么
public class NumberBlackHole
{

你没有跑过你发的的代码吧!结果不太对!
作者: liming1990422    时间: 2016-5-30 23:31
本帖最后由 liming1990422 于 2016-5-30 23:37 编辑

ArrayList<TreeSet<Integer>> a = new ArrayList<>();                 //装循环圈集合
                for (int i = 10000; i < 99999; i++) {
                        TreeSet<Integer> a1 = new TreeSet<>();          //装一个数的循环圈
                        a1 = hei(i, a1);
                        int d = 0;
                        for (TreeSet<Integer> tt : a) {
                                if (tt.equals(a1)) {                  //判断循环圈是否重复
                                        d = 1;
                                }
                        }
                        if (d != 1) {                                  //没有重复 加入循环圈集合
                                a.add(a1);
                        }
                }
                for (TreeSet<Integer> treeSet : a) {                     //遍历打印循环圈集合
                        System.out.println(treeSet);
                }
        }

        public static TreeSet<Integer> hei(int i, TreeSet<Integer> a) {
                Integer i1 = i;
                String s = i1.toString();
                char[] arr1 = s.toCharArray();
                Arrays.sort(arr1);
                int min = Integer.parseInt(String.copyValueOf(arr1));
                StringBuffer s1 = new StringBuffer(String.copyValueOf(arr1));
                StringBuffer s2 = s1.reverse();
                int max = Integer.parseInt(s2.toString());
                if ((a.add(max - min))) {
                        a.addAll(hei(max - min, a));
                }

                return a;
        }
瞅一瞅这个怎样 没有用0补前面的数
作者: 土菠萝    时间: 2016-5-30 23:44
liming1990422 发表于 2016-5-30 23:31
ArrayList a = new ArrayList();                 //装循环圈集合
                for (int i = 10000; i  ...

似乎不错,明天去跑跑看
作者: 土菠萝    时间: 2016-5-31 08:57
liming1990422 发表于 2016-5-30 23:31
ArrayList a = new ArrayList();                 //装循环圈集合
                for (int i = 10000; i  ...

[29997, 62964, 71973, 74943, 83952]
[39996, 62964, 71973, 74943, 83952]

你代码还能跑出这个答案,你觉得这个是黑洞数吗?两个都是?
作者: 土菠萝    时间: 2016-5-31 09:08
public static void main(String args []){
                final List<Integer> listFrist = new ArrayList<>();
                listFrist.add(1);
                for(int k=10001;k<100000;k++){
                        try {
                                List<Integer> resultList= new ArrayList<>();
                                resultList =resultArray(k, resultList, k, 1);
                                if(resultList.size()>0){
                                        boolean isUser = false;
                                        for(Integer first:listFrist){
                                                if(resultList.contains(first)){
                                                        isUser =true;
                                                }
                                        }
                                        if(!isUser){
                                                System.out.print("[");
                                                for (int i = 0; i < resultList.size(); i++) {
                                                        if(i==resultList.size()-1){
                                                                System.out.print(resultList.get(i));
                                                        }else{
                                                                if(i==0){
                                                                        listFrist.add(resultList.get(i));       
                                                                }
                                                                System.out.print(resultList.get(i)+",");
                                                        }
                                                }
                                                System.out.println("]");
                                        }
                                }
                               
                        } catch (Exception e) {
                                continue;
                        }
                }
        }
        public static List<Integer> resultArray(int a,List<Integer> result,int b,int cishu) throws Exception{
                if(cishu<=5){                       
                        if(a == maxminCha(b)){
                                result.add(Integer.valueOf(b));
                               
                                return result;
                        }else{
                                result.add(Integer.valueOf(b));
                                return resultArray(a,result,maxminCha(b),++cishu);
                        }
                }else{
                        return null;
                }
               
        }
        /**
         * 计算一个5位数的最大最小 差值
         * @param a
         * @return
         * @throws Exception
         */
        public static int maxminCha(int a) throws Exception{
                char[] c=String.valueOf(a).toCharArray();
                int max=0;
                int min=0;
                char t ='0';
                for(int i=0;i<c.length;i++){
                        for(int j=0;j<c.length;j++){
                                if(c[j]>c[i]){
                                       
                                        t =        c[i];
                                        c[i] =c[j];
                                        c[j] =t;
                                }
                        }
                }
                for(int i=0;i<c.length;i++){
                        max+=Integer.valueOf(String.valueOf(c[i]))*Math.pow(10, c.length-1-i);
                        min+=Integer.valueOf(String.valueOf(c[i]))*Math.pow(10, i);
                }
                int cha=min-max;
                return cha;
        }
作者: liming1990422    时间: 2016-5-31 09:52
本帖最后由 liming1990422 于 2016-5-31 09:54 编辑
土菠萝 发表于 2016-5-31 08:57
[29997, 62964, 71973, 74943, 83952]
[39996, 62964, 71973, 74943, 83952]

难道这两个不是循环圈吗  你自己算算
作者: 土菠萝    时间: 2016-5-31 09:59
liming1990422 发表于 2016-5-31 09:52
难道这两个不是循环圈吗  你自己算算

[62964, 71973, 74943, 83952]这个是,但是最前面的 29997和39996就不知道干嘛的了
作者: liming1990422    时间: 2016-5-31 10:37
好吧   我把题目的意思理解错了

作者: wzl100520    时间: 2016-6-5 11:03
路过,,,
作者: yangben    时间: 2016-6-10 22:40
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {

        /**
         * 任意一个5位数,比如:34256,把它的各位数字打乱,重新排列,可以得到一个最大的数:65432,一个最小的数23456。求这两个数字的差,得:
         * 41976,把这个数字再次重复上述过程(如果不足5位,则前边补0)。如此往复,数字会落入某个循环圈(称为数字黑洞)。
         * 比如,刚才的数字会落入:[82962, 75933, 63954, 61974] 这个循环圈。
         * 请编写程序,找到5位数所有可能的循环圈,并输出,每个循环圈占1行。其中5位数全都相同则循环圈为 [0],这个可以不考虑。
         * [53955,59994] [61974,82962,75933,63954] [62964,71973,83952,74943]
         */
        public static void main(String[] args) {
                // 定义一个嵌套集合存所有的数字黑洞
                List<List<Integer>> list_list = new ArrayList<>();

                for (int i = 10000; i < 100000; i++) {
                        // 把数字黑洞从返回的集合中分离出来,并存到另一个集合中
                        ArrayList<Integer> list = getList(new ArrayList<Integer>(), i);
                        List<Integer> temp = new ArrayList<>();
                        // 因为返回集合的最后一个元素就是这个数字黑洞的开始数字,倒数第二个元素就是这个数字黑洞的结束数字,通过截取获得数字黑洞
                        temp.addAll(list.subList(list.indexOf(list.get(list.size() - 1)),
                                        list.size() - 1));
                        // 如果嵌套集合没包含这个数字黑洞就存储
                        if (!list_list.contains(temp)) {
                                list_list.add(temp);
                        }
                }
                // 得到的数字黑洞因为排序不一样会被认为是不同的集合,所有再去一次重复
                for (int i = 0; i < list_list.size() - 1; i++) {
                        for (int j = i + 1; j < list_list.size(); j++) {
                                if (list_list.get(i).containsAll(list_list.get(j))) {
                                        list_list.remove(j--);
                                }
                        }
                }
                // 遍历所有的数字黑洞
                for (List<Integer> arrayList : list_list) {
                        System.out.println(arrayList);
                }

        }

        // 获取每一个5位数的数字黑洞,并存在一个ArrayList<Integer>集合中
        public static ArrayList<Integer> getList(ArrayList<Integer> list, int a) {
                // 获取每一个相减后的结果
                Integer result = getResult(a);
                // 如果集合中没有相减后的结果这个元素,则把结果添加到集合中,并递归调用
                if (!list.contains(result)) {
                        list.add(result);
                        getList(list, result);
                        // 如果集合中有了相减后的结果这个元素,说明这个数字黑洞开始了下一轮循环,
                        // 此时相减后的结果是这个数字黑洞的开始,并且把这个开始的数字存在集合末尾
                } else {
                        list.add(result);
                }
                // 返回带有数字黑洞的集合
                return list;
        }

        // 获取最大数和最小数的差
        public static Integer getResult(Integer b) {
                char[] arr = String.valueOf(b).toCharArray();
                // 如果是4位数加1个0
                if (arr.length == 4) {
                        String str = "0" + String.valueOf(b);
                        arr = str.toCharArray();
                        // 如果是3位数加2个0
                } else if (arr.length == 3) {
                        String str = "00" + String.valueOf(b);
                        arr = str.toCharArray();
                        // 如果是2位数加3个0
                } else if (arr.length == 2) {
                        String str = "000" + String.valueOf(b);
                        arr = str.toCharArray();
                        // 如果是1位数加4个0
                } else if (arr.length == 1) {
                        String str = "0000" + String.valueOf(b);
                        arr = str.toCharArray();
                }
                // 排序后会得到最小数的字符串表示形式
                Arrays.sort(arr);
                // 把字符串转成Integer对象
                Integer min = Integer.parseInt(String.valueOf(arr));
                // 反转后会得到最大数的字符串表示形式,再把字符串转成Integer对象
                Integer max = Integer.parseInt(new StringBuilder(String.valueOf(arr))
                                .reverse().toString());
                // 返回相减后的结果
                Integer result = max - min;
                return result;
        }
}
作者: 大笑哈哈    时间: 2016-6-19 14:09
牛逼啊,学习了
作者: 黄晓蚁    时间: 2016-6-21 10:35
这是面试题???  
作者: 大笑哈哈    时间: 2016-6-28 17:58
public static void main(String[] args) {
                //list集合记录黑洞数的循环圈
                ArrayList<Integer> list = new ArrayList<>();
                //listEnd集合记录所有循环圈元素,用于去除相同循环圈
                ArrayList<Integer> listEnd = new ArrayList<>();
                for(int i = 10000 ; i < 100000 ; i ++ ) {
                        list.clear();
                        if(judge(i,list) != -1) {
                                if(!listEnd.containsAll(list)){
                                        System.out.println(list);
                                        listEnd.addAll(list);
                                }
                        }
                }
        }
       
        //判断一个数是否是黑洞数,并将循环圈存入list集合
        private static int judge(int num, ArrayList<Integer> list) {
                list.add(num);
                int max = getMax(num);
                int min = getMin(num);
                int temp = max - min;
                //集合第一个元素的值和temp相等num就是黑洞数
                if(list.get(0) == temp){
                        //list.add(temp);
                        return num;
                } else {
                        //如果递归99次
                        if(list.size() >= 100){
                                //返回-1
                                return -1;
                        } else {
                                //否者继续递归
                                judge(temp,list);
                        }
                }
                //最终返回值,如果递归满99次就返回-1
                if(list.size() >= 100) {
                        return -1;
                //否者返回num
                }else {
                        return num;
                }
        }
       
        //获取5位数的可能排列的最大值
        private static int getMin(int num) {
                int[] arr = splitNum(num);
                return arr[0]*10000 + arr[1]*1000 + arr[2]*100        + arr[3]*10        + arr[4];
        }

        //获取5位数的可能排列的最大值
        private static int getMax(int num) {
                int[] arr = splitNum(num);
                return arr[4]*10000 + arr[3]*1000 + arr[2]*100        + arr[1]*10        + arr[0];
        }
       
        //拆分5位数获得一个大小为5的排序后的数组
        private static int[] splitNum(int num) {
                int ge = num % 10;
                int shi = num / 10 % 10;
                int bai = num / 100 % 10;
                int qian = num / 1000 % 10;
                int wan = num / 10000 % 10;
                int[] arr = new int[]{ge,shi,bai,qian,wan};
                Arrays.sort(arr);
                return        arr;
        }
作者: 代码是什么    时间: 2016-7-4 21:41
看的一脸懵逼
作者: miqideliwu    时间: 2016-7-24 14:03
土菠萝 发表于 2016-5-29 00:11
蓝桥杯是什么东西,反正我自己写出来一份,只是想参考一下其他的答案而已啦! ...

蓝桥杯是为推动软件开发技术的发展,促进软件专业技术人才培养,向软件行业输送具有创新能力和实践能力的高端人才,提升高校毕业生的就业竞争力,全面推动行业发展及人才培养进程,工业和信息化部人才交流中心特举办“全国软件专业人才设计与创业大赛”
作者: 周军福    时间: 2016-9-21 01:42
这是面试题???  




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2