遞歸算法與優化后的算法對比


前段時間看了《【面試】——反應遲鈍的遞歸》中的三個遞歸算法,斐波那契數列優化后的算法思路確實不錯,但是后面2個數列用遞歸的話,個人感覺有點得不償失。能不用遞歸的話,盡量不用,因為有些算法完全可以用數學來解決。因此,本文中將這三個數列的最終算法總結如下。

1、計算數組1,1,2,3,5,8,13...第30位的值

遞歸算法如下:

         public  static  int CalculateFibonacciSequence( int index)
        {
             if (index <=  0)
            {
                 return  0;
            }

             if (index ==  1 || index ==  2)
            {
                 return  1;
            }

             return CalculateFibonacciSequence(index -  1) + CalculateFibonacciSequence(index -  2);
        }

用遞歸算法來計算的話,有很多重復性的操作,采用數組相對來說,效率更高,最終算法如下:

         public  static  int CalculateFibonacciSequence( int index)
        {
             if (index <=  0)
            {
                 return  0;
            }

             if (index ==  1 || index ==  2)
            {
                 return  1;
            }

             int[] fibonacciArray =  new  int[index];
            fibonacciArray[ 0] =  1;
            fibonacciArray[ 1] =  1;

             for ( int innerIndex =  2; innerIndex < fibonacciArray.Length; innerIndex++)
            {
                fibonacciArray[innerIndex] = fibonacciArray[innerIndex -  1] + fibonacciArray[innerIndex -  2];
            }

             return fibonacciArray[index -  1];
        }

對於斐波那契數列,通用公式為Fn=F(n-1)+F(n-2)(n>=2,n∈N*),直接循環計算一次就可以獲得所需的值。

 

2、計算1+2+3+4+...+n的值

遞歸算法如下:

         public  static  int CalculateNumberSequenceCount( int index)
        {
             if (index <=  0)
            {
                 return  0;
            }

             return CalculateNumberSequenceCount(index -  1) + index;
        }

當數字(index)很大時,用上面的遞歸算法肯定是有問題的,我們看下最終的算法,如下所示:

         public  static  int CalculateNumberSequenceCount( int index)
        {
             if (index <=  0)
            {
                 return  0;
            }

             return index * (index +  1) /  2;
        }

對於1+2+3+4+...+n,完全是高中數學的等差數列求和的一個特例。1+2+3+4+......+n等於(首項+末項)*項數/2,所以結果為n(n+1)/2 。這個完全可以不用遞歸來進行計算,公式套用一下就解決了。

 

3、計算1-2+3-4+5-6+7+...+n的值

遞歸算法如下:

         public  static  int CalculateNumberSequence( int index)
        {
             if (index <=  0)
            {
                 return  0;
            }

             return index %  2 ==  0 ? CalculateNumberSequence(index -  1) - index : CalculateNumberSequence(index -  1) + index;
        }

對於1-2+3-4+5-6+7+...+n,可以分為2種情況,分別為:

(1)當n是偶數時,1-2+3-4+5-6+7+...+n=(1-2)+(3-4)+(5-6)+……+[(n-1)-n]

                                                            =-1×(n/2)

                                                            =-n/2

(2)當n是奇數時,1-2+3-4+5-6+7+...+n=(1-2)+(3-4)+(5-6)+……+[(n-2)-(n-1)]+n

                                                            =-1×(n-1)/2 +n

                                                            =(n+1)/2

因此,最終的算法如下:

         public  static  int CalculateCrossNumberSequence( int index)
        {
             if (index <=  0)
            {
                 return  0;
            }

             return index %  2 ==  0 ? -index /  2 : (index +  1) /  2;
        }

 

能夠用數學解決的問題,盡量不要用遞歸來進行計算。當然,很多情況還是需要用遞歸的。這里並不是說遞歸算法不好,只能說具體問題采用最優方式來解決才是最終的方案,希望對各位有所幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM