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

简介: 本文为原创,如需转载,请注明作者和出处,谢谢! 最近看了有道出的几个复赛题,觉得很好玩,现给出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开发速学宝典》出版, 欢迎定购

目录
相关文章
|
19天前
|
存储 算法 Java
Java:查找一个给定数组中的最大值和最小值
Java:查找一个给定数组中的最大值和最小值
|
3天前
|
Java 开发者 UED
掌握Java多线程编程:从基础到高级
【5月更文挑战第31天】本文深入探讨了Java多线程编程的核心概念,包括线程的创建、生命周期、同步机制以及高级并发工具。通过实际示例和代码片段,读者将学会如何有效地管理和协调线程,以编写高效且稳定的并发应用程序。
|
3天前
|
安全 Java 调度
Java语言多线程编程技术深度解析
Java语言多线程编程技术深度解析
134 1
|
3天前
|
存储 安全 Java
深入理解Java并发编程:线程安全与锁机制
【5月更文挑战第31天】在Java并发编程中,线程安全和锁机制是两个核心概念。本文将深入探讨这两个概念,包括它们的定义、实现方式以及在实际开发中的应用。通过对线程安全和锁机制的深入理解,可以帮助我们更好地解决并发编程中的问题,提高程序的性能和稳定性。
|
4天前
|
缓存 监控 安全
Java的线程池和线程安全
Java的线程池和线程安全
|
3天前
|
安全 算法 Java
Java中的并发编程技术:解锁高效多线程应用的秘密
Java作为一种广泛应用的编程语言,其并发编程技术一直备受关注。本文将深入探讨Java中的并发编程,从基本概念到高级技巧,帮助读者更好地理解并发编程的本质,并学会如何在多线程环境中构建高效可靠的应用程序。
|
3天前
|
Java
Java中多线程的常见实现方式
Java中多线程的常见实现方式
11 2
|
3天前
|
Java 调度
Java中的多线程编程:基础知识与实践
【5月更文挑战第31天】本文将深入探讨Java中的多线程编程,从基础知识到实践应用,全面解析多线程的概念、创建、同步以及在实际应用中的运用。我们将通过实例来展示如何在Java中有效地使用多线程,以提高程序的性能和响应速度。
|
3天前
|
存储 安全 Java
Java语言中的多线程编程技术深入解析
Java语言中的多线程编程技术深入解析
119 1
|
3天前
|
安全 Java
JAVA语言中的多线程编程技术
JAVA语言中的多线程编程技术