題目選自以下博客網址:
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)] 區間的幾個因子相關。每個因子可能對應一個解,但是也可能這個因子沒有解。
for ( int i = 2 ; i < imax;i ++ )
{
if ((n * 2 ) % i == 0 )
{
// 我們找到了i是2n的一個因子
temp = n * 2 - i * 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級。求總共有多少總跳法,並分析算法的時間復雜度。
首先我們考慮最簡單的情況。如果只有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里面完整顯示出來:
遞歸算法有一個很受限制的地方,它占用棧空間以深度的級數速度增長,如果深度太大,會迅速達到空間上限。因此只適合較淺深度求解。