題目是這樣的:
假設你正在爬樓梯,一共有N階樓梯。但每次你只能爬一階或者兩階,你能有多少種不同的方法爬到樓頂部?
初出茅廬,面試被問到,回家做個筆記記錄一下。
最先想到的應該是用遞歸的方法解:
public static int climbStairs1(int n) { int ways; if(n==1||n==2) { ways = n; }else { ways = climbStairs1(n-1)+climbStairs1(n-2); } return ways; }
這樣解表面固然沒毛病,但是學習算法的時候應該聽過遞歸的方法慎用,慎用,慎用!重要的事情說3遍...這個方法當N很大時,時間複雜度成指數型的增長,問題很大啊~
於是乎,面試官問道,你有什麼優化的方法嘛?(我有好的方法,不就直接寫出來了嘛?不過感覺面試官都喜歡由淺入深,( ̄▽ ̄)")
上網查詢了一下,確實有一些不一樣的方法:
public static int climbStairs2(int n) { if(n==0) return 1; int[] arr = new int[n+1]; arr[0]=1; arr[1]=1; for(int i=2;i<=n;i++) { arr[i] = arr[i-1]+arr[i-2]; } return arr[n]; }
這個方法是利用動態規劃來解決問題的,利用數組來存儲有多少種方法(與第一種那個方法比,實際就是利用空間換取時間,即空間複雜度很大),當N很大的時候,仍會出現問題,不過對於面試來說的話應該足夠了...
網上有種斐波那契數列的通項公式,有大神還能想得起來,做得出來,也是很強
public static int climbStairs4(int n) { if (n == 0) return 1; if (n == 1 || n == 2) return n; int result = (int) Math.floor( 1 / Math.sqrt(5) * (Math.pow((1 + Math.sqrt(5)) / 2, n + 1) - Math.pow((1 - Math.sqrt(5)) / 2, n + 1))); return result; }