• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 297,  comments - 15,  trackbacks - 0

            http://zhedahht.blog.163.com/blog/static/2541117420072915131422/題目:求1+2+…+n,要求不能使用乘除法、forwhileifelseswitchcase等關鍵字以及條件判斷語句(A?B:C)。

            分析:這道題沒有多少實際意義,因為在軟件開發中不會有這么變態的限制。但這道題卻能有效地考查發散思維能力,而發散思維能力能反映出對編程相關技術理解的深刻程度。

            通常求1+2+…+n除了用公式n(n+1)/2之外,無外乎循環和遞歸兩種思路。由于已經明確限制forwhile的使用,循環已經不能再用了。同樣,遞歸函數也需要用if語句或者條件判斷語句來判斷是繼續遞歸下去還是終止遞歸,但現在題目已經不允許使用這兩種語句了。

            我們仍然圍繞循環做文章。循環只是讓相同的代碼執行n遍而已,我們完全可以不用forwhile達到這個效果。比如定義一個類,我們new一含有n個這種類型元素的數組,那么該類的構造函數將確定會被調用n次。我們可以將需要執行的代碼放到構造函數里。如下代碼正是基于這個思路:

            class Temp
            {
            public:
                  Temp() { ++ N; Sum += N; }

                  static void Reset() { N = 0; Sum = 0; }
                  static int GetSum() { return Sum; }

            private:
                  static int N;
                  static int Sum;
            };

            int Temp::N = 0;
            int Temp::Sum = 0;

            int solution1_Sum(int n)
            {
                  Temp::Reset();

                  Temp *a = new Temp[n];
                  delete []a;
                  a = 0;

                  return Temp::GetSum();
            }

            我們同樣也可以圍繞遞歸做文章。既然不能判斷是不是應該終止遞歸,我們不妨定義兩個函數。一個函數充當遞歸函數的角色,另一個函數處理終止遞歸的情況,我們需要做的就是在兩個函數里二選一。從二選一我們很自然的想到布爾變量,比如ture1)的時候調用第一個函數,false0)的時候調用第二個函數。那現在的問題是如和把數值變量n轉換成布爾值。如果對n連續做兩次反運算,即!!n,那么非零的n轉換為true0轉換為false。有了上述分析,我們再來看下面的代碼:

            class A;
            A* Array[2];

            class A
            {
            public:
                  virtual int Sum (int n) { return 0; }
            };

            class B: public A
            {
            public:
                  virtual int Sum (int n) { return Array[!!n]->Sum(n-1)+n; }
            };

            int solution2_Sum(int n)
            {
                  A a;
                  B b;
                  Array[0] = &a;
                  Array[1] = &b;

                  int value = Array[1]->Sum(n);

                  return value;
            }

            這種方法是用虛函數來實現函數的選擇。當n不為零時,執行函數B::Sum;當n0時,執行A::Sum。我們也可以直接用函數指針數組,這樣可能還更直接一些:

            typedef int (*fun)(int);

            int solution3_f1(int i) 
            {
                  return 0;
            }

            int solution3_f2(int i)
            {
                  fun f[2]={solution3_f1, solution3_f2}; 
                  return i+f[!!i](i-1);
            }

            另外我們還可以讓編譯器幫我們來完成類似于遞歸的運算,比如如下代碼:

            template <int n> struct solution4_Sum
            {
                  enum Value { N = solution4_Sum<n - 1>::N + n};
            };

            template <> struct solution4_Sum<1>
            {
                  enum Value { N = 1};
            };

            solution4_Sum<100>::N就是1+2+...+100的結果。當編譯器看到solution4_Sum<100>時,就是為模板類solution4_Sum以參數100生成該類型的代碼。但以100為參數的類型需要得到以99為參數的類型,因為solution4_Sum<100>::N=solution4_Sum<99>::N+100。這個過程會遞歸一直到參數為1的類型,由于該類型已經顯式定義,編譯器無需生成,遞歸編譯到此結束。由于這個過程是在編譯過程中完成的,因此要求輸入n必須是在編譯期間就能確定,不能動態輸入。這是該方法最大的缺點。而且編譯器對遞歸編譯代碼的遞歸深度是有限制的,也就是要求n不能太大。

            大家還有更多、更巧妙的思路嗎?歡迎討論^_^

            本文已經收錄到《劍指Offer——名企面試官精講典型編程題》一書中,有改動。歡迎關注。我把這篇博客翻譯成了英文,感興趣的朋友可以到

            http://codercareer.blogspot.com/2011/10/no-08-calculate-12n.html查看。

            博主何海濤對本博客文章享有版權。網絡轉載請注明出處http://zhedahht.blog.163.com/。整理出版物請和作者聯系。對解題思路有任何建議,歡迎在評論中告知,或者加我微博http://weibo.com/zhedahht或者http://t.163.com/zhedahht與我討論。謝謝。
            from:
            http://zhedahht.blog.163.com/blog/static/2541117420072915131422/

            posted on 2012-07-05 10:04 chatler 閱讀(471) 評論(0)  編輯 收藏 引用 所屬分類: C++_BASIS
            <2010年1月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            常用鏈接

            留言簿(10)

            隨筆分類(307)

            隨筆檔案(297)

            algorithm

            Books_Free_Online

            C++

            database

            Linux

            Linux shell

            linux socket

            misce

            • cloudward
            • 感覺這個博客還是不錯,雖然做的東西和我不大相關,覺得看看還是有好處的

            network

            OSS

            • Google Android
            • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
            • os161 file list

            overall

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            久久久99精品成人片中文字幕 | 国产精自产拍久久久久久蜜| 99久久精品国内| 97久久天天综合色天天综合色hd| 久久综合给合久久国产免费| 久久久久四虎国产精品| 日韩中文久久| 2021久久精品国产99国产精品| 久久99精品国产麻豆不卡| 成人综合久久精品色婷婷| 人妻精品久久久久中文字幕69 | 亚洲人成网亚洲欧洲无码久久| 久久ww精品w免费人成| 国产高清国内精品福利99久久| 亚洲精品高清国产一线久久| 久久人人爽人爽人人爽av| 综合久久国产九一剧情麻豆| 青青草国产精品久久| 日本WV一本一道久久香蕉| 国产精品免费久久久久影院| 久久精品国产清高在天天线| 久久精品国产精品亚洲| 人人狠狠综合久久88成人| 久久天天躁狠狠躁夜夜躁2014| 成人a毛片久久免费播放| 久久婷婷五月综合色高清| 久久综合久久美利坚合众国| 色综合久久综合网观看| 久久国产成人精品麻豆| 久久久久久国产精品免费无码| 亚洲va久久久噜噜噜久久男同| 亚洲国产成人久久精品99 | 日产精品久久久久久久| 日韩精品无码久久久久久| 久久久噜噜噜www成人网| 亚洲国产精品无码久久一线| 亚洲中文精品久久久久久不卡| 国产欧美久久久精品影院| 久久久久久久精品成人热色戒| 热久久视久久精品18| 亚洲午夜无码久久久久小说|