<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
    數(shù)據(jù)加載中……

    有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)

    本文為原創(chuàng),如需轉(zhuǎn)載,請注明作者和出處,謝謝!

    最近看了有道出的幾個復(fù)賽題,覺得很好玩,現(xiàn)給出Java版的答案。先看看提干部分

        如果一個數(shù)字十進(jìn)制表達(dá)時,不存在連續(xù)兩位數(shù)字相等,則稱之為“不重復(fù)數(shù)”。例如,105,1234和12121都是“不重復(fù)數(shù)”,而11,100和 1225不算。給定一個long類型數(shù)字A,返回大于A的最小“不重復(fù)數(shù)”。 下面是幾個測試用例,我又加了幾個

    Examples:
    0)    54
        returns: 56
        大于54的最小數(shù)字是55,但55不是“不重復(fù)數(shù)”。下一個數(shù)字是56,它滿足條件。

    1)    10
        returns: 12

    2)    9
        returns: 10

    3)    98
        returns: 101
        99和100都不是“不重復(fù)數(shù)”, 101是。

    4)    21099
        returns: 21201

    5)  99123
        returns: 101010

    6)  1134567
        returns: 1201010

    ok,現(xiàn)在看看解題思路,其實這個題單純從題本身上看并不復(fù)雜,主要是效率問題。估計不會有人一個數(shù)一個數(shù)地循環(huán)查找吧,那樣如果給定的long數(shù)很大時,可能會進(jìn)行成千上萬次的循環(huán),會很慢很慢。技巧還是有的,現(xiàn)在來看看怎么快速搞定這個問題。
      
        首先來拿一個例子看,就選 21099了。
        這個數(shù)低兩位(99)是重復(fù)的。既然要找比21099大的最新不重復(fù)數(shù),就需要從這兩位開始遞增,但不是逐1的遞增。比21099大的數(shù)是21100,這個數(shù)也是個重復(fù)的數(shù),有兩對重復(fù)的(11和00)。從右側(cè)開始處理它們。先處理00。我們現(xiàn)在要做的就是把00變成不重復(fù)的,很簡單,就成01就可以了?,F(xiàn)在21100就變成了21101,這個數(shù)還是有兩個重復(fù)數(shù)(11)。現(xiàn)在處理11,把11變成12就不重復(fù)的,那么現(xiàn)在21101就變成了21201,ok,現(xiàn)在就得到了最終結(jié)果。我們看看,只結(jié)果了兩步,是很快地,因此,我們可以總結(jié)一下算法,步驟如下:
    1.  將給定的long數(shù)加1。
    2.  從這個數(shù)開始檢測是否為重復(fù)數(shù),如果不是,ok,這個數(shù)就是最終結(jié)果。如果是,那么從數(shù)的右側(cè)開始找第1對重復(fù)的數(shù),然后將其加1,得到一個新的數(shù)。
    3.  然后用這個數(shù)再從第2步開始。
    這個算法首先需要編寫一個方法用于將給定數(shù)最右側(cè)第一對重復(fù)的數(shù)找出,并且加1,最后得到一個新的數(shù)。如果這個數(shù)是不重復(fù)的數(shù),那么直接返回0。代碼如下:

        // sb表示指定的數(shù),以StringBuilder對象表示
        public static long getNextNum(StringBuilder sb)
        {
            String result 
    = "";
            
    char c = 'a'// c表示數(shù)字中待檢測位中高位的字符
            int i = 0;
            
    for (i = sb.length() - 1; i >= 0; i--)
            {
                
    // 如果相鄰的兩個數(shù)字不相同,那么將當(dāng)前字符保存在c中
                if (sb.charAt(i) != c)
                {
                    c 
    = sb.charAt(i);
                }
                
    // 如果相鄰的兩個數(shù)字相同,那進(jìn)行下一步地處理
                else
                {
                    
    // 將相同的兩個數(shù)字組成的數(shù)加1
                    long n = Long.parseLong(String.valueOf(c) + String.valueOf(c)) + 1;
                    
    // 先將這兩個相同的數(shù)字的位置的值設(shè)為0,以便進(jìn)行相加

                    
    // 計算數(shù)字后面要補(bǔ)的0的數(shù),如21443中重復(fù)的數(shù)字是44,加1后是45,那么首先將44設(shè)成00,
                    
    // 也就是21003,然后將45后面補(bǔ)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));
                   
    // 開始將重復(fù)數(shù)后面的數(shù)變成最小的
                    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;
        }
        要注意的是,雖然把每一對重復(fù)的數(shù)都變成了不重復(fù)的,但仍然不是最小的數(shù),需要將當(dāng)前重復(fù)數(shù)后面的數(shù)變成最小的,例如,99123將99變成不重復(fù)的數(shù),也就是100,原來的數(shù)變成了100123,但100123還需要繼續(xù)變成100101,再查找重復(fù)數(shù),把到了00,再變成101101,然后再變成101010,就ok了。
        最后調(diào)用getNextNum方法來返回最終結(jié)果,代碼如下:
        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;
        }

        現(xiàn)在可以使用下面的代碼來測試一下:
    System.out.println(getMinNoRepetitionNum(1999));




    Android開發(fā)完全講義(第2版)(本書版權(quán)已輸出到臺灣)

    http://product.dangdang.com/product.aspx?product_id=22741502



    Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


    新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

    posted on 2010-05-11 16:23 銀河使者 閱讀(3584) 評論(21)  編輯  收藏 所屬分類: javaalgorithm 、 原創(chuàng)

    評論

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    算法錯了,20097怎么辦?
    按你算法是20198
    實際應(yīng)該是20101
    2010-05-12 09:32 | zack

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)1  回復(fù)  更多評論   

    @zack
    少加了些代碼,現(xiàn)在ok了。
    2010-05-12 09:53 | 銀河使者

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    這個題如果給我做的話我不會從左往右檢查,相反我會從右往左檢查
    1.將數(shù)字+1
    2. 從左往右(從高位到低位)判斷是否有重復(fù)數(shù)字,沒有的話進(jìn)入4檢查到第一組重復(fù)數(shù)字進(jìn)入3
    2. 將兩個重復(fù)數(shù)字的以前的(包括重復(fù)數(shù)字取出來)并且+1,將結(jié)果*(10^n) + 01序列
    3. 輸出結(jié)果
    例 21001224321
    1.加1 = 21001224322
    2. 是重復(fù)數(shù)字進(jìn)入3
    3. 2100 *10^7 + 1* 10^7 + 1* 10^5 + 1* 10^3 + 1* 10^1 =
    21010101010
    4. 輸出 21010101010
    2010-05-12 18:24 | Zhjiang

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    @Zhjiang
    你寫的算術(shù)公式真的能算出這21010101010個數(shù)???

    我都不知道你怎么算出來的。
    2010-05-13 14:29 | Lancelot

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    @Lancelot
    試試不用知道了,計算機(jī)會告訴你的。
    2010-05-13 15:29 | 銀河使者

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    @銀河使者
    你知道10^7等于多少嗎???
    你把
    2100 *10^7 + 1* 10^7 + 1* 10^5 + 1* 10^3 + 1* 10^1
    算出來,你能等于21010101010嗎???

    拜托別說不負(fù)責(zé)任的話,只會讓自己獻(xiàn)丑。
    2010-05-13 16:33 | Lancelot

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    @銀河使者
    而且這個算式也與他上面寫的:
    2. 將兩個重復(fù)數(shù)字的以前的(包括重復(fù)數(shù)字取出來)并且+1,將結(jié)果*(10^n) + 01序列
    這句不符,明顯算式里沒有出現(xiàn)括號,那到底是先乘再取余(結(jié)果:21003)還是先取余再乘(結(jié)果:27348)?

    拜托你幫我算算是多少。
    在線等,謝謝。
    2010-05-13 16:41 | Lancelot

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    額 我想你們理解錯我的意思了

    10^n 我表示的是10的n次方

    不好意思啊
    2010-05-13 17:24 | Zhjiang

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    各位如果要有更好的算法,把代碼貼出來,不要光說一些理論。
    2010-05-13 18:28 | 銀河使者

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    什么都不說 粗略寫的java 代碼 大家研究下

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;


    public class Test {

    /**
    * @param args
    */
    public static void main(String[] args)
    {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String numStr =null;
    long num = -1;
    long tempnum = 0;
    long bitvalue = -1;
    int numbit1 = -1;
    int numbit2 = -1;
    int flag = -1;
    int size = 0;
    boolean isrepeater = false;

    try
    {
    numStr = br.readLine();
    num = Long.parseLong(numStr);

    } catch (NumberFormatException e)
    {
    return;
    } catch (IOException e)
    {
    return;
    }
    //只解析自然數(shù)
    if(num <= -1)
    return;

    size = (int)Math.log10(num);

    //1. 先將數(shù)字+1
    num ++;
    tempnum = num;

    //2. 判斷是否為重復(fù)數(shù)字
    if(tempnum / Math.pow(10, size) >= 1)
    size ++;

    bitvalue = (long)Math.pow(10, size - 1);

    for(flag = size - 1; flag >= 1; flag --){

    numbit1 = (int)(tempnum / bitvalue);

    tempnum = tempnum % bitvalue;

    bitvalue = (long)Math.pow(10, flag - 1);
    numbit2 = (int)(tempnum / bitvalue);

    if(numbit1 == numbit2){
    isrepeater = true;
    break;
    }
    }
    //2. 如果是重復(fù)數(shù)
    if(isrepeater){
    flag --;
    num -= tempnum % Math.pow(10, flag);

    //以下三行是由于考慮的遺漏,解決了以99開頭數(shù)字(例 9998)的問題
    //按照我以前的算法99123 得到的結(jié)果是100010
    num += (long)Math.pow(10, flag);
    if(Math.log10(num) >= size)
    num += (long)Math.pow(10, flag);

    flag -= 2;
    for(; flag >= 0; flag -=2){
    num += (long)Math.pow(10, flag);
    }
    }

    //4.輸出結(jié)果
    System.out.println(num);

    }

    }
    2010-05-13 18:30 | Zhjiang

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    我也只是剛剛寫的,遺漏之處和我說一下,謝謝了!
    在我看來這個題目純粹是一個計算的問題,不需要過多的循環(huán)的,當(dāng)然 僅爭對本題,另外解釋一點,我上面的代碼沒有把負(fù)數(shù)考慮進(jìn)去,只要稍微改進(jìn)一下就可以把負(fù)數(shù)也包括進(jìn)去,當(dāng)然這點還需要商榷,我只是一個猜想,因為準(zhǔn)備寫代碼的時候已經(jīng)下班了,不想在公司繼續(xù)熬了,所以代碼寫得很粗糙,沒有優(yōu)化,另外也沒有過多檢查BUG和遺漏的情況,往諒解下!
    2010-05-13 18:34 | Zhjiang

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    @Lancelot
    哈哈,上機(jī)測一下程序不就知道了。你不知道,可計算機(jī)知道哦。
    2010-05-14 08:23 | 銀河使者

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    看到你在Csdn上寫的,看來不止是我覺得擴(kuò)展01序列是一個不錯的方法!~~
    很慶幸
    2010-05-14 09:10 | Zhjiang

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    @銀河使者
    拜托你告訴我你用的什么計算機(jī)???
    你的計算機(jī)會把10^7算成3還是10000000???
    搞笑


    我都懶的理你了,這是最后一次回復(fù)你。
    2010-05-17 17:23 | Lancelot

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    @Lancelot
    什么意思,我的算法沒10^7,估計是你看到別人的回復(fù)算到我頭上了吧。如果認(rèn)為哪個具體的數(shù)無法通過算法,請指出,謝謝。

    對了,忘了說了,上星期我剛從某個外星種族那得到一臺先進(jìn)的計算機(jī),好象10^7既不等于3,也不等于10000000,等于^&%$&*^&*。 :)
    2010-05-17 19:33 | 銀河使者

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    Zhjiang的算法思路不錯, 不過還是有一些缺陷的.對于中間含有多個9的數(shù)字,處理不對。如99,1990,999...
    2010-05-17 23:42 | 曉風(fēng)待語

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    本人blog中有對該題的詳細(xì)解法,希望給予意見
    2010-05-17 23:45 | 曉風(fēng)待語

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)[未登錄]  回復(fù)  更多評論   

    確實覺得從左至右是合理的,
    比如說一個數(shù)字,567899882201
    首先+1,然后執(zhí)行如下步驟:
    步驟一:從左至右查找第一對重復(fù)的是99,操作:(567899 + 1)*10^6 =
    567900 000000
    其實這樣的操作會使任何一個數(shù)字都帶有0到n個0。如55 的話
    (55+1)*10^0 ,78662為:(7866+1)*10^1;
    步驟二:從左至右查找第一對重復(fù)的數(shù)字,如果重復(fù)的數(shù)字為0,即為00,執(zhí)
    行步驟三,否則執(zhí)行步驟一;
    步驟三:從左至右查找連續(xù)的兩個數(shù)字,此時連續(xù)的兩個數(shù)字只有可能是00了,
    如果有兩個連續(xù)的0,這時按照00+1,如:(567900+1)*10^6;

    只是寫了一個大致的實現(xiàn)思路,這個只是針對>=0的數(shù)字,^的意思是Math.pow(10, n);只是一個表現(xiàn)形式,大家也不用太糾結(jié)
    2010-06-25 10:56 | lj

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)[未登錄]  回復(fù)  更多評論   

    假如上個月(5月)總銷售額是39980,而本月(6月)總銷售額是59863,問:本月銷售同比上月銷售增長多少百分比,反比增長多少百分比?
    2010-07-03 13:35 | 小李

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    看了一下大伙的討論 覺得蠻有意思
    轉(zhuǎn)走了
    http://www.wangdacuo.com/archives/solve-question-use-java
    2010-07-13 19:26 | 特立獨(dú)行

    # re: 有道難題2009復(fù)賽題解答(Java版):求大于給定數(shù)的最小不重復(fù)數(shù)  回復(fù)  更多評論   

    我感覺這題好簡單啊……
    1.從高到低位掃描,遇到與高一位數(shù)相同的數(shù),就在該位置上加1,把該為后的全置0,
    2.重復(fù)1直到你掃描到個位且它與十位不同
    就搞定了……
    2011-04-28 22:41 | 喬磊
    主站蜘蛛池模板: 亚洲高清美女一区二区三区| 日本免费网站观看| 国产免费一区二区三区在线观看| jizz免费在线影视观看网站| 日韩在线一区二区三区免费视频 | 最好免费观看韩国+日本| 99精品全国免费观看视频| 日本一区二区三区免费高清| 毛片免费观看视频| 成人免费视频小说| 日韩高清在线高清免费| 免费人成在线观看视频播放| 免费国产a国产片高清网站| 免费一级做a爰片久久毛片潮喷| 国产一级大片免费看| 亚洲国产av一区二区三区| 亚洲日韩精品无码专区网站| 最新精品亚洲成a人在线观看| 亚洲国产精彩中文乱码AV| 亚洲av福利无码无一区二区| 久久久久亚洲AV无码麻豆| 亚洲妇女水蜜桃av网网站| 中文字幕亚洲综合小综合在线| 亚洲中文字幕久久无码| 亚洲Aⅴ在线无码播放毛片一线天| 欧洲精品码一区二区三区免费看| 一区二区三区免费电影| 97无码人妻福利免费公开在线视频| 久久免费视频99| 亚洲第一成年免费网站| 手机看片久久国产免费| JLZZJLZZ亚洲乱熟无码| 亚洲自偷自拍另类12p| 亚洲国产成人99精品激情在线| 日韩国产精品亚洲а∨天堂免| 一级毛片高清免费播放| 无码精品人妻一区二区三区免费看| 免费精品国产自产拍在| 亚洲国产精品毛片av不卡在线| 国产亚洲精品无码成人| 亚洲国产成人精品久久|