日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【剑指offer - C++/Java】10、矩形覆盖

發布時間:2023/12/10 c/c++ 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【剑指offer - C++/Java】10、矩形覆盖 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在線題目鏈接:矩形覆蓋

文章目錄

  • 1 題目描述
  • 2 題目分析
  • 3 代碼
    • 3.1 遞歸方法
      • 3.11 Java代碼
      • 3.12 C++代碼
    • 3.2 動態規劃算法
    • 3.2 動態規劃
      • 3.21 Java代碼
      • 3.22 C++代碼
    • 3.3 循環方法
      • 3.31 Java代碼
      • 3.32 C++代碼
  • 4、總結

1 題目描述

我們可以用2*1的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?

2 題目分析

乍一看感覺無從下手!!!其實如果我們使用歸納方法的話,總能夠總結出規律來。

假設下面是一個2*n的大矩形:

我們要使用下面這樣的2*1的小矩形來填滿上述的大矩形:

我們假設將2*n的矩形填滿需要f(n)種方法

那么填充的方法可以有下面的兩種方法:

  • 如下圖:2*1的矩形豎著放,那么還剩下2*(n-1)大小的矩形需要填,也就是剩下的矩形還有f(n-1)的方法填滿
  • 如下圖:2*1的矩形橫著放,那么由于它下面的也只能橫這放,所以還剩下2*(n-2)個矩形,也就是剩下的矩形需要有f(n-2)種方法填滿。
  • 很明顯,到這里我們就可以列出一個公式:

    • f(n)=f(n-1)+f(n-2)

    這個公式我們太熟悉了,這就是斐波那契數列,我們看下面三篇文章的算法題都是這個公式的應用:

    • 斐波那契數列
    • 跳臺階
    • 變態跳臺階

    綜上以及題目要求,我們得出綜合公式(n=0時f(n)=0):

    由此可以寫出三種不同的代碼:遞歸,動態規劃,循環

    3 代碼

    3.1 遞歸方法

    遞歸方法很簡單,直接利用公式即可。

    3.11 Java代碼

    public class Solution {public int RectCover(int target) {//遞歸if(target<3)return target;return RectCover(target-1)+RectCover(target-2);} }

    3.12 C++代碼

    class Solution { public:int rectCover(int number) {//遞歸if(number<3)return number;return rectCover(number-1)+rectCover(number-2);} };

    我們都知道這種遞歸解法會有很多重復的計算,就像下面的,假設我們要計算f(10):

    計算f(10),要重復計算兩次f(8),三次f(7),三次f(6),這種重復計算,對于數據比價大的時候,開銷是非常大的。所以我們經常說,遞歸雖然好寫,但是不建議在實現算法的時候使用遞歸算法。

    3.2 動態規劃算法

    3.2 動態規劃

    凡是能用遞歸寫出的代碼,一定能夠用動態規劃寫出來。

    我們知道遞歸是為了求某一個值,而必須先知道另外的幾個值后才能求出來。而想要求那另外的幾個值,還需要再求另外的另外的值,就像上面的遞歸二叉樹,想要先求f(10),必須知道f(9)和發(8)。想要知道f(9)又得知道f(8)和f(7)…

    上面遞歸是想要計算總體值,需要求局部的值,想要求局部的值,又要求局部的局部的值。

    動態規劃不是這樣,動態規劃是先從遞歸的終止條件開始計算,也就是說,動態規劃先計算局部的值,然后根據局部的值的累積,最終得到整體要求的值。也就是與遞歸反過來了。

    比如針對上面的求f(10),我們先求f(1),f(2),f(3)…最終肯定會求得f(10)。這樣我們就沒有進行重復的計算。每一項都是只計算一次。

    看代碼就能明白上面說的是什么意思了。下面的ret數組,ret[i]代表斐波那契數組的第i項。我們要求得第n項,最后求到ret[n]直接返回即可。

    3.21 Java代碼

    public class Solution {public int RectCover(int target) {//這同樣是斐波那契數列 f(n)=f(n-1)+f(n-2)//動態規劃if(target<=2)return target;int[] ret=new int[target+1];ret[1]=1;ret[2]=2;int i;for(i=3;i<=target;i++){ret[i]=ret[i-1]+ret[i-2];}return ret[target];} }

    3.22 C++代碼

    class Solution { public:int rectCover(int number) {//這同樣是斐波那契數列 f(n)=f(n-1)+f(n-2)//動態規劃//if(number<=2)return number;int ret[number+1];ret[0]=0;ret[1]=1;ret[2]=2;int i;for(i=3;i<=number;i++){ret[i]=ret[i-1]+ret[i-2];}return ret[number];} };

    3.3 循環方法

    所有的遞歸都可以寫成動態規劃,同理所有的動態規劃,也一定能寫成循環。只不過有的動態規劃不好寫成循環而已。本題是非常好寫成循環的。

    循環比動態規劃好的原因在于,循環只用幾個變量,循環使用它們得到最終結果,不保存之前的計算結果,動態規劃卻需要開辟一個數組,將所有計算過的結果保存,這很浪費空間。

    3.31 Java代碼

    public class Solution {public int RectCover(int target) {//循環if(target<3)return target;int r1=1,r2=2,ret=0;int i;for(i=3;i<=target;i++){ret=r1+r2;r1=r2;r2=ret;}return ret;} }

    當然,上面使用三個變量,我們還可以再減少一個變量,使用兩個變量:

    public class Solution {public int RectCover(int target) {//循環,更加單的寫法if(target<3)return target;int r1=1,r2=2;int i;for(i=3;i<=target;i++){r2+=r1;r1=r2-r1;}return r2;} }

    3.32 C++代碼

    三個變量

    class Solution { public:int rectCover(int number) {//循環if(number<3)return number;int r1=1,r2=2,ret=0;int i;for(i=3;i<=number;i++){ret=r1+r2;r1=r2;r2=ret;}return ret;} };

    兩個變量

    class Solution { public:int rectCover(int number) {//循環,更加單的寫法if(number<3)return number;int r1=1,r2=2;int i;for(i=3;i<=number;i++){r2+=r1;r1=r2-r1;}return r2;} };

    4、總結

    注意學會遞歸,動態規劃,循環三者時間的關系

    探討學習加:
    個人qq:1126137994
    個人微信:liu1126137994

    總結

    以上是生活随笔為你收集整理的【剑指offer - C++/Java】10、矩形覆盖的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。