1. 程式人生 > >leetcode 70. 爬樓梯問題(多種方法總結)

leetcode 70. 爬樓梯問題(多種方法總結)

爬樓梯問題有多種出現形式,有不固定最多可跨階數(即最多可跨階數為M,M作為方法引數)的,有固定每次最多可跨2階的。接下來,我就對以上兩種出線形勢分別進行分析。

(一)固定每次最多跨越2階,使用非遞迴方式實現:

1、問題描述: 

假設你正在爬樓梯。需要 n 階你才能到達樓頂。

每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?

注意:給定 n 是一個正整數。

 2、首先我們把 n<=5 的不同情況列出來:

1 2 3 4 5
1 2 3 5 8

綜上我們可以看出,爬樓梯的方案數f(n) = f(n) + f(n-1)

3、我們用java程式碼實現以上思路:

class Solution {
    public int climbStairs(int n) {
        if(n==1||n==2){
			return n;
		}
		int f1 = 1;
		int f2 = 2;
		int temp;
		for(int i=3; i<=n; i++){
			temp = f2;
			f2 += f1;
			f1 = temp;
		}
		return f2;  
    }
}

4、執行結果:

(二)使用遞迴方式實現

1、問題描述: 

假設一個樓梯有 N 階臺階,人每次最多可以跨 M 階,求總共的爬樓梯方案數。

 2、演算法實現(java語言):

private static int calculateCount(int ladder, int maxJump) {
	    int jump = 0;
	    if (ladder == 0) {
	        return 1;
	    }
	    if (ladder >= maxJump) {
	        // 剩下的樓梯大於最大可跳躍數
	        for (int i = 1; i <= maxJump; i++) {
	            jump += calculateCount(ladder - i, maxJump);	           
	        }
	    } else {
	        // 剩下的樓梯不足最大可跳躍數
	        jump = calculateCount(ladder, ladder);	        
	    }
	    return jump;
	}

(三)遞迴和非遞迴實現效能比較:

package test;

/**
 * 
 * @author FHY
 * 爬樓梯問題
 *
 */
public class DynamicTest {
	public static void main(String[] args) {
		//對遞迴和非遞迴實現兩種方法進行效能比較:
		long start = System.currentTimeMillis();
		getNums(30);
		long end1 = System.currentTimeMillis();
		System.out.println("非遞迴實現:"+(end1-start));
		
		calculateCount(30,2);
		long end2 = System.currentTimeMillis();
	    System.out.println("遞迴實現:"+(end2-end1));
	}
	
	private static int calculateCount(int ladder, int maxJump) {		
	    int jump = 0;
	    if (ladder == 0) {
	        return 1;
	    }
	    if (ladder >= maxJump) {
	        // 剩下的樓梯大於最大可跳躍數
	        for (int i = 1; i <= maxJump; i++) {
	            jump += calculateCount(ladder - i, maxJump);
	        }
	    } else {
	        // 剩下的樓梯不足最大可跳躍數
	        jump = calculateCount(ladder, ladder);
	    }	    
	    return jump;
	}

	public static int getNums(int n){
		if(n==1||n==2){
			return n;
		}
		int f1 = 1;
		int f2 = 2;
		int temp;
		for(int i=3; i<=n; i++){
			temp = f2;
			f2 += f1;
			f1 = temp;
		}		
		long end = System.currentTimeMillis();
		return f2;
	}
}

輸出:

非遞迴實現:0
遞迴實現:14

可見,遞迴實現效能很差!