走在架構師的大道上 Jack.Wang's home

          Java, C++, linux c, C#.net 技術,軟件架構,領域建模,IT 項目管理 Dict.CN 在線詞典, 英語學習, 在線翻譯

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks

           原題目:
           給定一個十進制數N,寫下從1開始,到N的所有整數,然后數一下其中出現的所有"1"的個數。
           例如:
           N=2,寫下1,2。這樣只出現了1個"1"
           N=12,寫下 1,2,3,4,5,6,7,8,9,10,11,12。這樣"1"的個數是5
           請寫出一個函數,返回1到N之間出現"1"的個數,比如 f(12)=5

           1package org.blogjava.arithmetic;
           2
           3/**
           4 * @author Jack.Wang
           5 * @see http://jack2007.blogjava.net/
           6 */

           7public class CountNumber {
           8
           9    private int count1Num(int num) {
          10        int sum = 0;
          11        while (num != 0{
          12            sum += (num % 10 == 1? 1 : 0;
          13            num /= 10;
          14        }

          15        return sum;
          16    }

          17
          18    private int countNum(int n) {
          19        int sum = 0;
          20        for (int i = 1; i <= n; i++{
          21            sum += count1Num(i);
          22        }

          23        return sum;
          24    }

          25
          26    private int countNumNew(int n) {
          27        int count = 0;
          28        int factor = 1;
          29        int lower;
          30        int current;
          31        int higher;
          32        while (n / factor != 0{
          33            lower = n - (n / factor) * factor;
          34            current = (n / factor) % 10;
          35            higher = n / (factor * 10);
          36            switch (current) {
          37            case 0:
          38                count += higher * factor;
          39                break;
          40            case 1:
          41                count += higher * factor + lower + 1;
          42                break;
          43            default:
          44                count += (higher + 1* factor;
          45            }

          46            factor *= 10;
          47        }

          48        return count;
          49    }

          50
          51    /**
          52     * @param args
          53     */

          54    public static void main(String[] args) {
          55        System.out.println("兩個算法的結果相等");
          56        /**
          57         * 方法一: 這個問題看上出并不是一個難問題,因為不需要太多的思考,只要稍懂點程序的人都會想到,簡單的設計如下。
          58         * 這個方法很簡單但是這個算法的致命問題是效率,它的時間復雜度是 O(N)*count(int num)函數的復雜度=
          59         * O(N)*logN。可見如果N很大時復雜度成線性增長。是否還有更好的方法,我說的是從算法復雜的角度考慮最優的方法? 
                              請看方法二。
          60         */

          61        long start = System.currentTimeMillis();
          62        CountNumber cn1 = new CountNumber();
          63        System.out.println("第一個算法的結果"+cn1.countNum(100000000));
          64        long end = System.currentTimeMillis();
          65        long time1 = end - start;
          66        /**
          67         * 方法二: 這種方法分別分析N的每一位上1出現的可能性,讀者可以自己按照歸納的思想分析一下,最終你會得出
          68         * 一個結論,就是通過分析N而不是遍歷1到N的每一個數就可以得出答案,如果N的長度為Len的話這種 算法的復雜度為O
                              (Len)。 發現規律為
          69         * 1. 如果位數上為0,1的數目由該位以上的數決定,并乘以該位的分位 比如百位上是0,高位上是14則百位上出現1的數目
                                  為 14*100。
          70         * 2. 如果位數上為1,1的數目由高位和低位共同決定。 比如高位是14低位是112,則百位出現1的數目為 14×100+(112+
                                  1) 
          71         * 3. 如果位數上大于1,則百位出現1的數目為 (14+1)×100
          72         */

          73        start = System.currentTimeMillis();
          74        CountNumber cn2 = new CountNumber();
          75        System.out.println("第二個算法的結果"+cn2.countNumNew(100000000));
          76        end = System.currentTimeMillis();
          77        long time2 = end - start;
          78        System.out.println("第一個算法的時延比第二個算法的多" + (time1 - time2) / 1000 + "");
          79    }

          80
          81    /**
          82     Console Out:
          83     兩個算法的結果相等
          84     80000001
          85     80000001
          86     第一個算法的時延比第二個算法的多27秒
          87     */

          88}

          89




          本博客為學習交流用,凡未注明引用的均為本人作品,轉載請注明出處,如有版權問題請及時通知。由于博客時間倉促,錯誤之處敬請諒解,有任何意見可給我留言,愿共同學習進步。
          posted on 2008-10-16 18:10 Jack.Wang 閱讀(4137) 評論(11)  編輯  收藏 所屬分類: 數學&算法

          Feedback

          # re: 微軟面試題---求出1的個數之小解 2008-10-16 22:07 testsssss
          N=12,寫下 1,2,3,4,5,6,7,8,9,10,12。這樣"1"的個數是5??  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-16 22:38 Jack.Wang
          @testsssss
          不好意思打錯了。  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-16 22:43 YYX
          @testsssss
          缺了個11  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-17 01:14 YYX
          不好意思,我借用你這道題目在cnblogs上發了一篇blog...  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-17 10:01 mr.s
          感覺沒什么用啊  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-17 12:36 Huangyy
          還有一種方法,就是轉成String 然后一個一個字符去匹配就OK  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-17 14:44 Lancelot
          只要將1-N的數字作為字符串疊加在一起,然后用"1"作為分隔符將字符串分割為數組,數組長度減一就是“1的個數”。  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-17 14:45 Lancelot
          當然要先排除只有一個"1"的情況。  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-17 17:01 YYX
          @Lancelot
          你大概以為字符串疊加這算法能達到o(N)復雜度
          但實際上這種就是NLogN復雜度的算法。
          因為Integer向String轉換過程中有LogN的復雜度。
          對每項數字都轉換,那總共就有NLogN的復雜度。
          如果你還想把數字都疊一起算,那么你的空間開銷都將由原來的LogN達到 NLogN  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-17 17:48 lvcha
          def f n
          result=0
          n.times do |i|
          result=result+(i.to_s).count('1')
          end
          return result
          end

          f 12
          12
          f 1200
          640
          當然速度是慢,可是工作中在你研究復雜度時我已經完成開發開始新的模塊了  回復  更多評論
            

          # re: 微軟面試題---求出1的個數之小解 2008-10-20 13:44 Reeze
          @lvcha
          這樣很無聊啊~~  回復  更多評論
            

          主站蜘蛛池模板: 关岭| 湖北省| 玉溪市| 平阴县| 涟源市| 太仓市| 历史| 南充市| 焦作市| 灵宝市| 肃南| 濮阳市| 沙坪坝区| 惠安县| 吴忠市| 桐乡市| 平舆县| 安西县| 孙吴县| 曲阜市| 定边县| 紫金县| 上虞市| 巍山| 永吉县| 偏关县| 南京市| 云浮市| 拜泉县| 台东县| 台州市| 车险| 铁岭县| 治多县| 老河口市| 广德县| 唐山市| 志丹县| 光泽县| 佛学| 平遥县|