目錄
一、回溯法簡介
回溯法(探索與回溯法)是一種選優搜索法,又稱爲試探法,按選優條件向前搜索,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術爲回溯法,而滿足回溯條件的某個狀態的點稱爲“回溯點”。回溯法很有趣可以解決一系列的問題,比如子集問題、排列問題以及八皇后問題等。是個很值得研究和學習的算法。可以細看我之前的博客https://blog.csdn.net/kupepoem/article/details/106662487和https://blog.csdn.net/kupepoem/article/details/106665698
二、動態規劃簡介
動態規劃程序設計是對解最優化問題的一種途徑、一種方法,而不是一種特殊算法。不像搜索或數值計算那樣,具有一個標準的數學表達式和明確清晰的解題方法。動態規劃程序設計往往是針對一種最優化問題,由於各種問題的性質不同,確定最優解的條件也互不相同,因而動態規劃的設計方法對不同的問題,有各具特色的解題方法,而不存在一種萬能的動態規劃算法,可以解決各類最優化問題。因此讀者在學習時,除了要對基本概念和方法正確理解外,必須具體問題具體分析處理,以豐富的想象力去建立模型,用創造性的技巧去求解。我們也可以通過對若干有代表性的問題的動態規劃算法進行分析、討論,逐漸學會並掌握這一設計方法。 可以參看我之前的博文。
三、題目
來源:https://leetcode-cn.com/problems/combination-sum-iv
給定一個由正整數組成且不存在重複數字的數組,找出和爲給定目標正整數的組合的個數。
示例:
nums = [1, 2, 3]
target = 4
所有可能的組合爲:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
請注意,順序不同的序列被視作不同的組合。
因此輸出爲 7。
四、實現
1、思路
這和Combination Sum1-3比較類似,沿用Combination Sum即可。沿用Combination Sum思路你會發現計算會超時,因爲枝幹實在是太多。那麼加入dp記錄下一些中間結果,進一步的進行剪枝。
2、回溯法遞歸
下面的回溯法遞歸代碼是會超時的。
int combinationSum_help2(vector<int>& candidates,int resval ,std::vector<int> &dp)
{
if (resval == 0)
{
return 1;//剪枝
}
else if(resval<0)
{
return 0;//剪枝
}
int sumres=0;
for (int i = 0; i < candidates.size(); ++i)
{
sumres+=combinationSum_help2(candidates, resval - candidates[i],dp);
}
dp[resval]=sumres;
return sumres;
}
int combinationSum4(vector<int>& nums, int target)
{
int res=0;
std::vector<int> dp;
dp.resize(target+1);
for(int i=0;i<target+1;i++)
dp[i]=-1;
int sum=combinationSum_help2(nums, target,dp);
return sum;
}
3、回溯法遞歸+dp
int combinationSum_help2(vector<int>& candidates,int resval ,std::vector<int> &dp)
{
if (resval == 0)
{
return 1;//剪枝
}
else if(resval<0)
{
return 0;//剪枝
}
if(dp[resval]!=-1)
return dp[resval];//剪枝
int sumres=0;
for (int i = 0; i < candidates.size(); ++i)
{
sumres+=combinationSum_help2(candidates, resval - candidates[i],dp);
}
dp[resval]=sumres;
return sumres;
}
int combinationSum4(vector<int>& nums, int target)
{
int res=0;
std::vector<int> dp;
dp.resize(target+1);
for(int i=0;i<target+1;i++)
dp[i]=-1;
int sum=combinationSum_help2(nums, target,dp);
return sum;
}
五、總結
算法設計還是要掌握其中的思想,掌握了思想問題也就迎刃而解了。