回溯法和动态规划轻松解决Combination Sum IV问题

 

目录

 

一、回溯法简介    

二、动态规划简介

三、题目

四、实现

1、思路

2、递归求解

3、递归代码+dp

五、总结


一、回溯法简介
    

      回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。回溯法很有趣可以解决一系列的问题,比如子集问题、排列问题以及八皇后问题等。是个很值得研究和学习的算法。可以细看我之前的博客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& candidates,int resval ,std::vector &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& nums, int target) 
{
		int res=0;
		std::vector dp;
		dp.resize(target+1);
		for(int i=0;i

3、回溯法递归+dp

int combinationSum_help2(vector& candidates,int resval ,std::vector &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& nums, int target)
{
		int res=0;
		std::vector dp;
		dp.resize(target+1);
		for(int i=0;i

五、总结

     算法设计还是要掌握其中的思想,掌握了思想问题也就迎刃而解了。

 

你可能感兴趣的:(算法)