递归思想
以下部分文字图片转自文章一眼看懂递归
递归是什么?
求解问题 f(6), 由于 f(6) = n * f(5), 所以 f(6) 需要拆解成 f(5) 子问题进行求解,同理 f(5) = n * f(4) ,也需要进一步拆分,… ,直到 f(1), 这是「递」,f(1) 解决了,由于 f(2) = 2 f(1) = 2 也解决了,… f(n)到最后也解决了,这是「归」
所以递归的本质是能把问题拆分成具有相同解决思路的子问题,。。。直到最后被拆解的子问题再也不能拆分,解决了最小粒度可求解的子问题后,在「归」的过程中自然顺其自然地解决了最开始的问题
什么时候用递归?
1.一个问题可以分解成具有相同解决思路的子问题,子子问题,换句话说这些问题都能调用同一个函数
2.经过层层分解的子问题最后一定是有一个不能再分解的固定值的(即终止条件),如果没有的话,就无穷无尽地分解子问题了,问题显然是无解的
满足以上两个条件即可用递归解决问题
怎么用递归?(四步法)
1.明确函数的功能
2.找出递推公式和临界条件(出口)
3.将递推公式表达出来写到函数里
4.推导时间复杂度,看看会不会超时==,超时就得换
回溯是啥?
就是返回去做上一层未做完的事情,因为函数变量的存活期只在当前函数,所以变量的值为上一个函数的值,return是一层一层的去回溯的
递归样例(后续有经典题)
(1)这里说一下斐波那契数列的结论:每月大土对数等于上两个月的大兔对数之和,即an=an-1+an-2
得知了这个递归公式,我们就可以写出递归函数
代码实现如下
#include<stdio.h>
int Fibonacci (int n)
{
if(n==0) return 0;
else if(n==1) return 1;
else
return Fibonacci(n-1)+Fibonacci(n-2);
}
int main()
{
int n;
while(~scanf("%d",&n))
printf("%d\n\n",Fibonacci (n));
}
(2)我们可以用递归实现累加
代码实现如下,若输入3,此函数输出3+2+1=6
int recursion(int n)
{
if(n==1) return 1;
return n+recursion(n-1);
}
int main()
{
int n,ans;
scanf("%d",&n);
printf("%d",recursion(n););
}
回溯样例
无回溯的递归如下,此函数输出 1 2 3 4 5
void a(int x)
{
if(x>5) return; //结束条件
printf("%d\n",x);
a(x+1); //递归语句
}
int main()
{
a(1);
return 0;
}
(4)有回溯的递归,return语句每次返回一层,执行剩下的语句
代码实现如下,此函数输出1 2 3 4 5 然后开始回溯 5 4 3 2 1
void a(int x)
{
if(x>5) return; //结束条件
printf("%d\n",x);
a(x+1);//递归语句
printf("%d\n",x); //回溯要执行的语句 (还债)
}
int main()
{
a(1);
return 0;
}