人理解循环,神理解递归---1

所有的递归都是穷举

递归本身就是把所有符合题意的情况穷举出来,任何用递归实现的算法都可以用循环穷举出来。

为什么?

递归总要有一个结束的条件,而这个结束的条件一定在算法本身是被收敛回来的

结束条件的函数值也必须是已知的

用递归算组合问题

从n个数里面选k个数,有多少种选法

首先需要清楚,从n个数中选k个数等于从n-1个数中选k-1个数加上从n-1个数中选k个数

比如从1,2,3,4,5中选3个数

等于

第一个选1与第一个不选1两种情况的总和

而第一个选1之后剩下4个数再选两个

第一个不选1就是从剩下的4个中选3个

记住这两个待解决的问题,只要把这两个问题解决了,最终答案就出来了

那现在这个问题还是没能直接知道答案,那为了解决这个问题,就把这两个问题再分解,

从4个数里面选2个有多少中选法?

等于

从3个里面选2个加上从2个里面选2个

上面这两个问题第一个从3个里面选2个还没知道答案,那好,再分解,但是

从2个里面选2个有一种选法,直接返回1即可,那好这个问题解决了,

那我们再去解决从3个数里面选2个的问题

3选2 等于

从2个里面选1  加上 从2个里面选2个

这个问题的答案直接知道了,那好,

返回去

3选2知道了答案,2选2知道了答案

那4选2的答案知道了

 

上面同理4选3答案也可以这样递推出来,

现在4选2知道了答案,4选3知道了答案

那5选3的答案就知道了

这样分析是不是很扯呢

是的

这样转成代码一个一个的写出来要写8个函数,总共调用11次,如果再往上加还要写更多的函数

如果不懂递归,那就只能这样一个一个穷举了,不会多,也不会漏。

写吧,8个函数,谁让咱不聪明呢,

int exe_count = 0;

int C22()
{
	exe_count++;
	return 1;
}
int C21()
{
	exe_count++;
	return 2;

}
int C31()
{
	exe_count++;
	return 3;
}

int C32()
{
	exe_count++;
	return C22() + C21();
}
int C33()
{
	exe_count++;
	return 1;
}
int C43()
{
	exe_count++;
	return C32() + C33();
}

int C42()
{
	exe_count++;
	return C32() + C31();
}

int C53()
{
	exe_count++;
	
	return C42() + C43();
}

int main()
{

	cout << C53() << endl;
	cout << exe_count << endl;
}

 

这个5个选3个还能这么写,再多两个也还能玩,那要是100个呢,那就只能骂出题的了

骂完之后发现,没什么叼用

那我们就想办法能不能把这么多函数合并起来,少写那么几个,OK

上面的函数算的内容都是一样的,从n个数里面选k个,那就把n和k写成变量传进去吧

int C(int n,int k)
{

    
}

当调用这个函数,传入参数的时候,发现这个函数还调用了他本身

int C(int n,int k)
{
    return C(n-1,k)+C(n-1,k-1);
    
}

这样调用下去,它死循环啊

什么时候返回呢,就是能明确知道答案的时候返回

那怎么写呢

用if判断啊,好,干

从上面的的直接返回数值的函数我们可以知道从n个里面选一个,我们是可以直接知道答案有n中选法

从k个里面选k个我们也是可以直接知道答案有1种选法

那来吧

int C(int n, int k)
{
    c_exe_count++;
	if (n == k)
	{
		return 1;
	}
	if (k == 1)
	{
		return n;
	}
	return C(n - 1, k) + C(n - 1, k - 1);

}

上面就是一个递归了

在n=5,k=3时

执行它跟执行上面的8个函数完全是一样的

你说一样就一样吗,试试吧

int main()
{

	cout << C53() << endl;
	cout << C(5, 3) << endl;

	cout << exe_count << endl;
	cout << c_exe_count << endl;

	return 0;
}

这是递归的最直观的感受了

递归说白了就是穷举,一个一个枚举出来,但是又不想去写那么多的函数,单单用循环又特么写不出来

下面总结一下

什么情况下用递归

在所需要解决的问题随着参数的变大需要计算的步骤逐渐增多的时候,这种“逐渐”大多数时候是呈指数级增长的

但是又能明确知道参数变量很小时的答案

而同时,又能把这种多参数的问题解剖为一个同类的小一级的参数的问题

这条件也太苛刻了吧

我反正是在项目中没用过递归

去写这个纯粹是个人想了解一下,发散一下思维

下面是网上看到的一个递归三要素的内容

1.明确函数的目的

就是清晰的定义你这个函数是用来做什么的。比如我上面那个函数,我这个函数就是用来计算从n个数里面选k个数的选择方式有多少种的。

2.明确函数结束的条件。即函数在什么情况下能返回。

3.明确函数的等价关系,只需要明白一点,就是我那个需要解决的问题,与分解成小一级的问题的关系

比如我上面写的那个函数,从5个数里面选3个

就是分解成   从4个里面选3个数 加上 从4个里面选2个数

告诉函数我这个问题的解决方式就够了,至于更小的问题,不需要你去思考,上面的函数结束条件会知道怎么处理的

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

究极调参工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值