动态规划——斐波那契数列(70. 爬楼梯、198. 打家劫舍、213. 打家劫舍II、信件错排、母牛生产)
遞歸和動態規劃都是將原問題拆分成多個子問題然后求解,但是動態規劃存儲了子問題的解,不需要重復計算.
動態規劃(Dynamic Programming,DP)需要轉移方程和邊界條件。
目錄
一、70. 爬樓梯
1.1 題目描述
1.2 代碼
二、198. 打家劫舍
2.1 題目描述
2.2 代碼
三、213. 打家劫舍 II
3.1 題目描述
3.2 代碼
四、信件錯排
4.1 題目描述
4.2 代碼
五、母牛生產
5.1 題目描述
5.2 代碼
?
1.1 題目描述
假設你正在爬樓梯。需要?n?階你才能到達樓頂。
每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定?n?是一個正整數。
1.2 代碼
思路鏈接
思路和算法:
用 f(x)表示爬到第 x級臺階的方案數,考慮最后一步可能跨了一級臺階,也可能跨了兩級臺階。
1.動態規劃的轉移方程:
f(x) = f(x - 1) + f(x - 2)
2.再討論邊界條件:我們是從第 0 級開始爬的,所以從第 0 級爬到第 0?級我們可以看作只有一種方案,即 f(0) = 1;從第 0級到第 1?級也只有一種方案,即爬一級,f(1) = 1。根據轉移方程得到 f(2) = 2,f(3) = 3,f(4) = 5,……
public int climbStairs(int n){int pre1=1,pre2=1;for (int i = 1; i < n; i++) {int temp=pre2pre2=pre1+pre2;pre1=temp;}return pre2;}復雜度分析:
時間復雜度:循環執行 n 次,每次花費常數的時間代價,故漸進時間復雜度為 O(n)。
空間復雜度:這里只用了常數個變量作為輔助空間,故漸進空間復雜度為 O(1)。
補充
還有兩種其他方法:
- 隨著 n的不斷增大 O(n) 可能已經不能滿足我們的需要了,我們可以用「矩陣快速冪」的方法把算法加速到O(logn)。
- 我們也可以把 n?代入斐波那契數列的通項公式計算結果,但是如果我們用浮點數計算來實現,可能會產生精度誤差。
?
二、198. 打家劫舍
2.1 題目描述
你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
給定一個代表每個房屋存放金額的非負整數數組,計算你 不觸動警報裝置的情況下 ,一夜之內能夠偷竊到的最高金額。
2.2 代碼
題解思路
如果房屋數量大于兩間,應該如何計算能夠偷竊到的最高總金額呢?對于第 k?(k>2) 間房屋,有兩個選項:
- 偷竊第 k 間房屋,那么就不能偷竊第k?1 間房屋,偷竊總金額為前k?2 間房屋的最高總金額與第 k 間房屋的金額之和。f(k-2)+mk
- 不偷竊第k 間房屋,偷竊總金額為前 k?1 間房屋的最高總金額。f(k-1)
如果有一間房,則偷這一間f1=m1。若有兩間房,則偷金額多的那一個f2=max{m1,m2}。如果有三間房,則f3=max{{m1,m3},{m2}},即f3=max{f1+m3,f2}。
如果有四間房,若偷前兩間房的最大的加上第4間,或者前3間房的,即{f2+m4}or f3,因此f4=max{{f2+m4},f3}。
可以寫出轉移方程:
public static int rob(int[] nums) {if (nums.length==1) return nums[0];int pre1=nums[0],pre2=Math.max(nums[0],nums[1]);for (int i = 2; i < nums.length; i++) {int temp=pre2;pre2=Math.max(pre1+nums[i],pre2);pre1=temp;}return pre2;}復雜度分析
時間復雜度:O(n),其中 n是數組長度。只需要對數組遍歷一次。
空間復雜度:O(1)。使用滾動數組,可以只存儲前兩間房屋的最高總金額,而不需要存儲整個數組的結果,因此空間復雜度是 O(1)。
?
三、213. 打家劫舍 II
3.1 題目描述
你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都 圍成一圈 ,這意味著第一個房屋和最后一個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警 。
給定一個代表每個房屋存放金額的非負整數數組,計算你 在不觸動警報裝置的情況下 ,今晚能夠偷竊到的最高金額。
3.2 代碼
題解思路
假設數組nums 的長度為 n。如果不偷竊最后一間房屋,則偷竊房屋的下標范圍是[0,n?2];如果不偷竊第一間房屋,則偷竊房屋的下標范圍是 [1,n?1]。
在確定偷竊房屋的下標范圍之后,即可用第 198 題的方法解決。
public static int rob(int[] nums) {int n=nums.length;if (nums==null || n == 0) return 0;if (n == 1) return nums[0];if (n == 2) return Math.max(nums[0], nums[1]);return Math.max(robRange(nums,0,n-2),robRange(nums,1,n-1));}public static int robRange(int[] nums,int start,int end){int pre1 = nums[start], pre2 = Math.max(nums[start], nums[start+1]);for (int i = start+2; i <= end; i++) {int temp=pre2;pre2 = Math.max(pre1 + nums[i], pre2);pre1 = temp;}return pre2;}?
四、信件錯排
4.1 題目描述
??NowCoder每天要給很多人發郵件。有一天他發現發錯了郵件,把發給A的郵件發給了B,把發給B的郵件發給了A。于是他就思考,要給n個人發郵件,在每個人僅收到1封郵件的情況下,有多少種情況是所有人都收到了錯誤的郵件?
即有 N 個信件和信箱,每封信件對應一個正確信箱位置?,F在它們被打亂,求錯誤裝信方式的數量。保證每一封信都裝在錯誤的位置。
4.2 代碼
思路:
數組dp[],存儲錯誤方式數量。dp[i]表示有i封信、i個信箱情況下的錯誤裝信方法總數。
對于第N封信而言,假設其裝在了第 K 個信箱中,對于第 K 封信,有兩種情況,(1)信件 K 裝在信箱 N 中;(2)信件 K 未被裝在信箱 N 中。
(1)?信件K裝在信箱N中
我們不看 K 和 N 這兩對信件和信箱,只關注剩下 N-2 對信件和信箱,有 dp[N-2] 種錯誤裝信方法。同時, K 的取值范圍: 1~N-1 ,因此共有 (N-1)*dp[N-2] 種錯誤裝信方法。
(2) 信件 K 未被裝在信箱 N 中
?
先給出結果,該情況的錯誤裝信方法有 (N-1)*dp[N-1] 種。這個 dp[N-1] 是如何得出來,我思考了良久。
我們把問題重新描述一下,思路就會清晰很多。事實上,對于信件 i 來說,信箱 i 是它的“專屬信箱”,每個信件都不能放入自己的專屬信箱,對于n 個信件而言,都需要找其它 n-1 個信箱放入,其錯排方法數為 dp[n] 。
問題的癥結在于,對于上圖中的信件 K 來說,其專屬信箱,即 K 信箱已經被占用。
但是,我們可以把信箱 N 當做信件 K 的“專屬信箱”,因為本情況下,信件 K 也不能放入信箱 N 。所以可以理解成求 N-1 封信件和 N-1 個信箱(除去信件 N)之間的錯排數量問題。所以得到 dp[N-1]。
同理 K 的取值范圍: 1~N-1 ,因此共有 (N-1)*dp[N-1] 種錯誤裝信方法。
綜上,狀態轉移方程:
private int MailMisalignment(int n){if (n==0) return 0;if (n==1) return 1;int[] dp =new int[n];dp[0]=0;dp[1]=1;for (int i = 2; i < n; i++) {dp[i]=(i-1)*(dp[i-1]+dp[i-2]);}return dp[n-1];}?
五、母牛生產
5.1 題目描述
??假設農場中成熟的母牛每年都會生 1 頭小母牛,并且永遠不會死。第一年有 1 只小母牛,從第二年開始,母牛開始生小母牛。每只小母牛 3 年之后成熟又可以生小母牛。給定整數 N,求 N 年后牛的數量。
5.2 代碼
思路:
??每一年的母牛數等于前一年的母牛數和三年前的母牛數。用dp[i]代表第i+1年的母牛數量。
轉移方程:dp[ i ]=dp[i-1]+dp[i-3]
邊界條件:dp[0]=1;dp[1]=2;dp[2]=3;//第一年有1個母牛,第二年有2個,第三年有3個母牛
public int cowNums(int n){if (n<=3) return n;int dp[]=new int[n];dp[0]=1;dp[1]=2;dp[2]=3;for (int i = 3; i <n ; i++) {dp[i]=dp[i-1]+dp[i-3];}return dp[n-1];}?
總結
以上是生活随笔為你收集整理的动态规划——斐波那契数列(70. 爬楼梯、198. 打家劫舍、213. 打家劫舍II、信件错排、母牛生产)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: office启动出现oxc0000142
- 下一篇: 话说中国足球