有道难题2009复赛题解答(Java版):求大于给定数的最小不重复数

本文为原创,如需转载,请注明作者和出处,谢谢!

最近看了有道出的几个复赛题,觉得很好玩,现给出Java版的答案。先看看提干部分

    如果一个数字十进制表达时,不存在连续两位数字相等,则称之为“不重复数”。例如,105,1234和12121都是“不重复数”,而11,100和 1225不算。给定一个long类型数字A,返回大于A的最小“不重复数”。 下面是几个测试用例,我又加了几个

Examples:

0)    54

    returns: 56

    大于54的最小数字是55,但55不是“不重复数”。下一个数字是56,它满足条件。

1)    10

    returns: 12

2)    9

    returns: 10

3)    98

    returns: 101

    99和100都不是“不重复数”, 101是。

4)    21099

    returns: 21201

5)  99123

    returns: 101010

6)  1134567

    returns: 1201010

ok,现在看看解题思路,其实这个题单纯从题本身上看并不复杂,主要是效率问题。估计不会有人一个数一个数地循环查找吧,那样如果给定的long数很大 时,可能会进行成千上万次的循环,会很慢很慢。技巧还是有的,现在来看看怎么快速搞定这个问题。

    首先来拿一个例子看,就选 21099了。

    这个数低两位(99)是重复的。既然要找比21099大的最新不重复数,就需要从这两位开始递增,但不是逐1的递增。比21099大的数是21100,这 个数也是个重复的数,有两对重复的(11和00)。从右侧开始处理它们。先处理00。我们现在要做的就是把00变成不重复的,很简单,就成01就可以了。 现在21100就变成了21101,这个数还是有两个重复数(11)。现在处理11,把11变成12就不重复的,那么现在21101就变成了 21201,ok,现在就得到了最终结果。我们看看,只结果了两步,是很快地,因此,我们可以总结一下算法,步骤如下:

1.  将给定的long数加1。

2.  从这个数开始检测是否为重复数,如果不是,ok,这个数就是最终结果。如果是,那么从数的右侧开始找第1对重复的数,然后将其加1,得到一个新的数。

3.  然后用这个数再从第2步开始。

这个算法首先需要编写一个方法用于将给定数最右侧第一对重复的数找出,并且加1,最后得到一个新的数。如果这个数是不重复的数,那么直接返回0。代码如 下:

    // sb表示指定的 数,以StringBuilder对象表示
    public static long getNextNum(StringBuilder sb)
    {
        String result = "";
        char c = 'a'; // c表示数字中待检测位中高位的字符
        int i = 0;
        for (i = sb.length() - 1; i >= 0; i--)
        {
            // 如果相邻的两个数字不相同,那么将当前字符保存在c中
            if (sb.charAt(i) != c)
            {
                c = sb.charAt(i);
            }
            // 如果相邻的两个数字相同,那进行下一步地处理
            else
            {
                // 将相同的两个数字组成的数加1
                long n = Long.parseLong(String.valueOf(c) + String.valueOf(c)) + 1;
                // 先将这两个相同的数字的位置的值设为0,以便进行相加

                // 计算数字后面要补的0的数,如21443中重复的数字是44,加1后是45,那么首 先将44设成00,
                // 也就是21003,然后将45后面补0,就是450,最后用21003和450相 加,就变成了21453
                int m = sb.length() - i - 2;
                sb.setCharAt(i, '0');
                sb.setCharAt(i + 1, '0');
                for (int k = 0; k < m; k++)
                    n *= 10;
                long num = Long.parseLong(sb.toString()) + n;
                sb = new StringBuilder(String.valueOf(num));
                // 开始将重复数后面的数变成最小的
                m = i + 2;
                for (int x = m; x < sb.length(); x++)
                {
                    for (int y = 0; y < 10; y++)
                    {
                        
                        if (sb.charAt(x - 1) != (y + 48))
                        {
                            sb.setCharAt(x, (char) (y + 48));
                            break;
                        }
                    }
                }

                return Long.parseLong(sb.toString());
            }
        }
        return 0;
    }

    要注意的是,虽然把每一对重复的数都变成了不重复的,但仍然不是最小的数,需要将当前重复数后面的数变成最小的,例如,99123将99变成不重复的数, 也就是100,原来的数变成了100123,但100123还需要继续变成100101,再查找重复数,把到了00,再变成101101,然后再变成 101010,就ok了。

    最后调用getNextNum方法来返回最终结果,代码如下:

    public static long getMinNoRepetitionNum(long num)
    {
        String s = String.valueOf(num + 1);

        long n = 0;
        long result = 0;
        while ((n = getNextNum(new StringBuilder(s))) != 0)
        {
            s = String.valueOf(n);
            result = n;
        }
        if (result == 0)
            return num + 1;
        else
            return result;
    }

    现在可以使用下面的代码来测试一下:

System.out.println(getMinNoRepetitionNum(1999));

乐博Android手机客户端(新浪微博)发布

《银 河系列原创教程》发布

《Java Web开发速学宝典》出版, 欢迎定购

时间: 2024-09-28 07:32:18

有道难题2009复赛题解答(Java版):求大于给定数的最小不重复数的相关文章

c语言-两道C语言编程题:求教各位大神

问题描述 两道C语言编程题:求教各位大神 两元一瓶啤酒,两个啤酒瓶换一瓶啤酒,四个啤酒瓶盖换一瓶啤酒,输入的金额可以买几瓶. 输入一串字符串,写两个函数,第一个函数使输入的字符串全都后移一位,第二个函数将字符串中的字母大写换小写,小写换大写?. 拜托各位了 谢谢~ 解决方案 第一个问题描述不清,不知道是不是可以借啤酒瓶和瓶盖,我的程序按照不可以编写: #include <stdio.h>int foo(int money){ int c = money / 2; int c1 = 0; int

方法-初学的IT女孩,求正确解答JAVA基础概念

问题描述 初学的IT女孩,求正确解答JAVA基础概念 在面向对象编程里,每个对象...选择下面一个正确选项: a. 是另一个对象的一个属性 b. 是一个类的一个实例 c. 继承一个类 d. 具有递归方法 选择正确的语句或者JAVA里关于面向对象编程的语句(多选题) ? 继承模型IS-A关系,其中子类的对象还是超类的对象. ? 在一个超类里的方法的数量总是高于其每一个子类 ? 同样的超类的两个子类总是有相同数量的方法. 在JAVA里选择正确的关于可见度的答案.当一个属性(实例变量)在一个类里被定义

编程-java 问题 求大神解答

问题描述 java 问题 求大神解答 第三题,我们老师说是选D,汉字能做标识符吗? 解决方案 A 肯定不行,是关键字.自己定义几个试一试就知道了~ 解决方案二: java中,命名规范是允许字母,下划线,$符的,汉字也可以,但一般不建议使用.你那题里面A interface是接口关键字,肯定不可以的 解决方案三: 汉字是可以做标示符的 string 字符串: int 数字: 都是可以通过编译的: 因为java语言是以UNICODE字符集为基础的,而汉字恰恰也包括在UNICODE字符中 解决方案四:

求解答java报错问题运行出错,求帮助

问题描述 求解答java报错问题运行出错,求帮助 16:29:21,442 ERROR ContextLoader:215 - Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl': Injection of resource fields failed; nested except

图片-Java新人求解答:自己制作一个网站,出现问题,求详细解答。

问题描述 Java新人求解答:自己制作一个网站,出现问题,求详细解答. 我自己制作了一个网站,该网页上设定了插入图片这一选项,可是当我插入一张名为 Peter_Jackson.jpg 的图片后,网页上没有显示, 而且myeclipse的console还报出了如下错误: java.io.FileNotFoundException: C:mysoftwareapache-tomcat-7.0.37webappsfriend2uploadpic_3E:David_LiupicturePeter_Jac

java-初学者求大神解答JAVA问题

问题描述 初学者求大神解答JAVA问题 java中字符串数组排序 Arrays.sort() 是按西安大写后小写拍的 但是我想讲笑a排在B之前 有什么方法能实现 最好不是新建一个方法 解决方案 /* package whatever; // don't place package name! */ import java.util.*; import java.lang.*; import java.io.*; class C implements Comparator { public int

功率谱估计-谁会这俩道自适应滤波的题啊,时域离散随机信号处理方面的,急急急,求大神

问题描述 谁会这俩道自适应滤波的题啊,时域离散随机信号处理方面的,急急急,求大神 跪求大神啊!有关于数字信号处理中的时域离散随机信号处理的内容,真的很急!大神!大神! 解决方案 题就是这两张图上的,求大神给出上帝之手!

求解答java通过请求头如何得到文件类型后缀

问题描述 求解答java通过请求头如何得到文件类型后缀 java中,上传一个文件,首先要从文件的请求头中得到文件的内容类型,然后判断文件的扩展名,请知道的大神详细解答! 解决方案 貌似httpservletRequest'类能够获取请求头,查查api有你要的一切 解决方案二: 上传文件,直接从请求体中得到文件的全部信息啊,什么名字,内容,大小都能得到了 解决方案三: 直接使用httprequest就行,具体的方法可以查一下api 解决方案四: 使用commo-fileupload.jar 大概步

“有道难题”举办 周枫互联网发展趋势

近日,据腾讯报道,由网易有道举办的2012"有道难题"开放日成功举行,网易公司高级副总裁周枫在会上表示:移动客户端是未来互联网发展的趋势.网易愿意将这些技术和经验带到蓬勃发展的市场,同时帮助有潜力.有资质的人才实现技术梦想,这无疑给那些心怀理想的创业者又注射了一针强心剂. 据了解,2012有道难题自报名以来就吸引众多技术达人和高校学生的关注.截止目前,已经有超过3000支团队报名参加本届创新大赛,报名学生团队来自清华大学.北京大学.复旦大学.南京大学.中山大学等全国41所重点高校. &