牛客网在线编程专题《剑指offer-面试题9:相关题目》矩形覆盖

题目链接:

https://www.nowcoder.com/practice/72a5a919508a4251859fb2cfb987a0e6?tpId=13&tqId=11163&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述:

 牛客网在线编程专题《剑指offer-面试题9:相关题目》矩形覆盖_第1张图片

 解题思路:

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];
    }

}

相关题目:

【1】牛客网在线编程专题《剑指offer-面试题9》斐波那契数列

【2】牛客网在线编程专题《剑指offer-面试题9:题目二扩展》变态跳台阶

【3】牛客网在线编程专题《剑指offer-面试题9:题目二》跳台阶

【4】【LeetCode】198. House Robber

你可能感兴趣的:(剑指offer,动态规划,矩形覆盖,算法,剑指offer)