1. 程式人生 > >牛客網線上程式設計專題《劍指offer-面試題9:相關題目》矩形覆蓋

牛客網線上程式設計專題《劍指offer-面試題9:相關題目》矩形覆蓋

題目連結:

題目描述:

 

 解題思路:

2*n的大矩形,和n個2*1的小矩形

其中2*target為大矩陣的大小,target也是小矩形的個數。

有以下幾種情形:

  • target <= 0 大矩形為2*0,直接return 1;
  • target = 1大矩形為2*1,只有一種擺放方法,return1;
  • target = 2 大矩形為2*2,有兩種擺放方法,return2;
  • target = n 分為兩步考慮:

我們假設target=8,把2*8的覆蓋方法記為f(8)。用第一個1*2小矩陣去覆蓋大矩陣的最左邊時有兩個選擇,豎著放或者橫著放。當豎著放的時候,右邊還剩下2*7的區域,這種情形下的覆蓋方法記為f(7)。接下來考慮橫著放的情況。當1*2的小矩陣橫著放在左上角的時候,左下角也必須橫著放一個1*2的小矩形,而在右邊還剩下2*6的區域,這種情形下的覆蓋方法記為f(6),因此f(8)=f(7)+f(6)。此時我們可以看出,這仍然是斐波那契數列。

解題方法:

(1)遞迴法

已經AC的程式碼:

public class rectangleCover {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(RectCover(0));
	}
	
    public static int RectCover(int target) {
    	if(target == 0)
    		return 0;
    	else if(target == 1)
    		return 1;
    	else if(target == 2)
    		return 2;
    	else {
			return RectCover(target - 1) + RectCover(target - 2);
		}
    	
    }

}

(2)記憶化搜尋法

由於遞迴的解法有很多重複的計算,我們把已經計算過的f(n)儲存在陣列中,等再需要f(n)的時候,直接從陣列中讀取,這就是記憶化搜尋演算法的核心思想。

已經AC的程式碼:

import java.util.Arrays;

public class rectangleCover {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(RectCover(33));
	}
	
	public static int[] memo;
	
    public static int RectCover(int target) {
    	memo = new int[target + 1];
    	Arrays.fill(memo, -1);
    	return coverNum(target);
    }
    
    public static int coverNum(int n) {
        if(memo[n] != -1)
            return memo[n];
        else if(n == 0)
            memo[0] = 0; 
    	else if(n == 1)
    		memo[1] = 1;
    	else if(n == 2)
    		memo[2] = 2;
    	else {
				memo[n] = coverNum(n-1) + coverNum(n-2);
		}
		return memo[n];
    }

}

(3)動態規劃解法

狀態轉移方程:f(n)=f(n-1)+f(n-2)

邊界條件:f(0) = 0、f(1) = 1、f(2) = 2。

已經AC的程式碼:

import java.util.Arrays;

public class rectangleCover {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(RectCover(3));
	}
	
    public static int RectCover(int target) {
    	int[] memo = new int[target + 1];
    	Arrays.fill(memo, -1);
    	if(target == 0)
    		memo[0] = 0;
    	if(target == 1)
    		memo[1] = 1;
    	if(target == 2)
    		memo[2] = 2;
    	if(target > 2) {
    		memo[0] = 0;
    		memo[1] = 1;
    		memo[2] = 2;
    		for(int i=3; i<=target; i++) {
    			if(memo[i] == -1)
    				memo[i] = memo[i-1] + memo[i-2];
    			}
    	}
    	return memo[target];
    }

}

相關題目: