程序員面試題100題(一)(轉)


題目選自以下博客網址:
http://zhedahht.blog.163.com/#。

第26題:
題目:輸入一個正數n,輸出所有和為n連續正數序列。

例如輸入15,由於1+2+3+4+5=4+5+6=7+8=15,所以輸出3個連續序列1-5、4-6和7-8。

分析:這是網易的一道 面試題

我自己的思路:
首先想到的是等差數列的求和,即(m1+(m1+k-1))*k=n*2,  其中起始數字start=m1,結束數字end=m1+k-1;
因此這道題目的解和n*2的因子有關,解的集合在2n的在 [2,sqrt(2n)] 區間的幾個因子相關。每個因子可能對應一個解,但是也可能這個因子沒有解。

int  imax = ( int )Math.Sqrt(n * 2 ) + 1 ;
for ( int  i = 2 ; i < imax;i ++ )
{
    
if ((n * 2 ) % i == 0 )
    {
        
// 我們找到了i是2n的一個因子
        temp = n * 2   -  i * +  i;
        
if ( temp % (i * 2 ) == 0 )
        {
            
// 我們發現這個因子確實是一個解
            start = temp / (i * 2 );
            end
= start +  i  - 1 ;
            Console.WriteLine(
" {0}-{1} " , start,end);
        }
    }
}

當n=30000時,輸出結果如下:

9999-10001
5998-6002
1993-2007
1188-1212
922-953
363-437
265-360
178-302
108-267

我覺得它的好處是代碼量較少,清晰易讀。


————————————————————————————————————————
第23題:跳台階問題
題目:一個台階總共有n級,如果一次可以跳1級,也可以跳2級。求總共有多少總跳法,並分析算法的時間復雜度。

分析:這道題最近經常出現,包括MicroStrategy等比較重視算法的公司都曾先后選用過個這道題作為面試題或者 筆試題

首先我們考慮最簡單的情況。如果只有1級台階,那顯然只有一種跳法。如果有2級台階,那就有兩種跳的方法了:一種是分兩次跳,每次跳1級;另外一種就是一次跳2級。

現在我們再來討論一般情況。我們把n級台階時的跳法看成是n的函數,記為f(n)。當n>2時,第一次跳的時候就有兩種不同的選擇:一是第一次只跳1級,此時跳法數目等於后面剩下的n-1級台階的跳法數目,即為f(n-1);另外一種選擇是第一次跳2級,此時跳法數目等於后面剩下的n-2級台階的跳法數目,即為f(n-2)。因此n級台階時的不同跳法的總數f(n)=f(n-1)+(f-2)。

我們把上面的分析用一個公式總結如下:

        /  1                          n=1
f(n)=      2                          n=2
        \  f(n-1)+(f-2)               n>2

分析到這里,相信很多人都能看出這就是我們熟悉的Fibonacci序列。

問題的解,是一個樹形結構,我引入了TreeView中的節點TreeNode來成生這個樹,它是一個典型遞歸:

// 組裝一個根節點成為一顆樹
     static   void  AddNode(System.Windows.Forms.TreeNode root, int  n)
    {
        
if (n > 2 )
        {
            root.Nodes.Add(
" 1 " );
            root.Nodes.Add(
" 2 " );
            AddNode(root.Nodes[
0 ],n - 1 );
            AddNode(root.Nodes[
1 ],n - 2 );
            
        }
        
else   if (n == 1 )
        {
            root.Nodes.Add(
" 1 " );
        }
        
else   if (n == 2 )
        {
            root.Nodes.Add(
" 1 " );
            root.Nodes[
0 ].Nodes.Add( " 1 " );
            
            root.Nodes.Add(
" 2 " );
        }
    }

樹組裝好以后,每一個葉子節點的全路徑就是一個解,因此將葉子節點的FullPath(路徑)打印出來即為一個解,這里為了找到葉子節點,也是使用遞歸:

// 打印出所有葉子節點的全路徑
static   void  PrintNode(TreeNode node)
{
    
// 屬於葉子節點!!!!則打印這個路徑
     if (node.Nodes.Count == 0 )
        Console.WriteLine(node.FullPath);
    
else
    {
        
foreach (TreeNode child  in  node.Nodes)
        {
            PrintNode(child);
        }
    }
}

當輸入n=5時,打印出所有葉子節點的FullPath如下:

root\1\1\1\1\1
root\1\1\1\2
root\1\1\2\1
root\1\2\1\1
root\1\2\2
root\2\1\1\1
root\2\1\2
root\2\2\1

我們可以把一個解在一個TreeView里面完整顯示出來:
www.wityx.com

遞歸算法有一個很受限制的地方,它占用棧空間以深度的級數速度增長,如果深度太大,會迅速達到空間上限。因此只適合較淺深度求解。


免責聲明!

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



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