[LeetCode] 動態規劃入門題目
最近接觸了動態規劃這個厲害的方法,還在慢慢地試著去了解這種思想,因此就在LeetCode上面找了幾道比較簡單的題目練了練手。
首先,動態規劃是什麽呢?很多人認為把它稱作一種“算法”,其實我認為把它稱作一種“思想”更為合適;利用動態規劃去解決問題,其實就是逐步遞推的過程,與貪心算法不同,動態規劃遞推的每一步都要求是當前的最優解(這是很重要的,遞推的正確性依賴的就是這一點);利用動態規劃解題時,必須自己定義出來狀態和狀態轉移方程。然而,看上去簡單,做起來卻非常困難,因為解題時的具體形式千差萬別,找出問題的子結構以及通過子結構重新構造最優解的過程很難統一。
經典的動態規劃題目有背包問題、硬幣問題等等,可以通過這些題目去理解一下這個東西。
我認為,動態規劃最難的就是找出狀態方程。同時,個人認為比較難的是,懂得去利用“前面每一步都是最優解”這一點。
廢話不多說,直接看看LeetCode上簡單的動態規劃題目。
要註意的是,下面的三題都用到了局部最優和全局最優解法:
1.Jump Game
原題地址:https://leetcode.com/problems/jump-game/description/
解法:
用一個global變量保存到目前為止能跳的最遠距離,用一個local變量保存當前一步出發能跳的最遠距離,這題裏面的狀態就是走到每一步時的global[i]值,狀態轉移方程就是global[i] =max{nums[i] + i, global[i-1]}。當然,寫代碼的時候用變量代替數組即可。
class Solution { public: bool canJump(vector<int>& nums) { int reach = 0; for (int i = 0; i < nums.size() - 1 && reach >= i; i++) { reach = nums[i] + i > reach ? nums[i] + i : reach; } return reach >= nums.size() - 1; } };
2.Maximum Subarray
原題地址:https://leetcode.com/problems/maximum-subarray/description/
解法:
這一題要維護兩個變量:global和local,與上面一題一樣,local保存包含當前元素的最大值(局部最優),global保存的是所有情況裏面的最大值(全局最優)。假設第i步的local[i]和global[i]已知,那麽第i+1步的local[i + 1] = max{ nums[i] + local[i], nums[i + 1] },global[i + 1] = max{global[i], local[i + 1]}。代碼如下:
class Solution { public: int maxSubArray(vector<int>& nums) { int global = nums[0], local = nums[0]; for (int i = 1; i < nums.size(); i++) { local = nums[i] > nums[i] + local ? nums[i] : nums[i] + local; global = local > global ? local : global; } return global; } };
3.Best Time to Buy and Sell Stock
原題地址:https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/
這道題目有兩種方法,其實都是動態規劃:
(1)
class Solution { public: int maxProfit(vector<int>& prices) { if (prices.size() == 0) return 0; int maxPrice = prices[prices.size() - 1]; int res = 0; for (int i = prices.size() - 1; i >= 0; i--) { maxPrice = max(maxPrice, prices[i]); res = max(res, maxPrice - prices[i]); } return res; } };
這種解法在這個博客裏面講得很詳細:http://www.cnblogs.com/remlostime/archive/2012/11/06/2757434.html
(2)局部最優和全局最優解法:
class Solution { public: int maxProfit(vector<int>& prices) { if (prices.size() == 0) return 0; int local = 0, global = 0; for (int i = 1; i < prices.size(); i++) { local = max(0, local + prices[i] - prices[i - 1]); global = max(local, global); } return global; } };
local = max(0, local + prices[i] - prices[i - 1])這一句,我一開始在考慮:為什麽不寫成local = max(local, local + prices[i] - prices[i - 1])呢?
後來想了一下,因為假如這樣寫,有可能得到的就不是包含當前元素的局部最優解了。所以,在“局部最優和全局最優解法”裏面,永遠不會出現local=local的情況。
這篇文章講的都是具體題目的解法,要真正理解動態規劃,真的要多做題,多找規律。
[LeetCode] 動態規劃入門題目