1. 程式人生 > >劍指offer之青蛙跳臺階

劍指offer之青蛙跳臺階

題目描述

一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果)。

求解思路

剛開始是想要通過遞迴模擬求解,結果超時了。但是這樣肯定能求出解來,不過計算了大量重複的程式碼,複雜度應該是指數級的。 正確的思路應該是:

  • 先計算出最多能放幾個2步,假設是n個
  • i從1到n,計算i個2步的情況下步法的組合數,所有組合數累加到sum上
  • sum+1是最終解,因為全是1的情況也要考慮

複習排列組合的公式: Anm=n(n1)(nm+1)=n!(nm)!A_{n}^{m}=n(n-1)\cdots (n-m+1)=\frac{n!}{(n-m)!}

Cnm=Anmm!=n!m!(nm)!=n(n1)(n2)(nk+1)(nk)(nk1)2×1C_{n}^{m}=\frac{A_{n}^{m}}{m!}=\frac{n!}{m!(n-m)!}=\frac{n(n-1)(n-2)\cdots(n-k+1)}{(n-k)(n-k-1)\cdots 2\times1}

解題程式碼

#include <bits/stdc++.h>
using namespace std;
// 這是超時的,但是結果正確 class Solution_failed { public: int jumpFloor(int number) { int sum = 0; if(number == 0) { return 1; } else if(number < 0) { return 0; } else { sum += jumpFloor(number - 1); // 跳一個 sum += jumpFloor(number -
2); // 跳兩個 return sum; } } }; // 這是AC的程式碼,使用了階乘 class Solution { public: int jumpFloor(int number) { // 只要確定了2步的位置,1步的位置隨便插入 int n = number / 2; int sum = 1; for(int i = 1; i <= n; ++i) { // 注意,每增加一個2,總的空位置就要少一個, int t = comp(number - i, i); sum += t; } return sum; } // 計算組合數 int comp(int n, int k) { long long up = 1, down = 1; for(int i = n; i >= n - k + 1; i--) { up *= i; } for(int j = k; j >= 1; j--) { down *= j; } return up / down; } }; // 以下是測試 int main() { Solution_failed sof; Solution so; for(int i = 1; i <= 10; ++i) { // 輸出結果一致 cout << sof.jumpFloor(i) << "," << so.jumpFloor(i) << endl; } return 0; }