精华内容
下载资源
问答
  • 递归的要点

    2021-03-29 21:20:22
    递归函数大准侧 1,必须要有一基准,这基准不需要用递归即可算出 2,程序必须向基准靠近 比如求0-100和 public static int sum(int x){ if(x==0) return 0; else return sum(x-1)+x; } 以x=0为基准,和为0,...

    递归函数两大准侧
    1,必须要有一个基准,这个基准不需要用递归即可算出
    2,程序必须向基准靠近
    比如求0-100的和
    public static int sum(int x){
    if(x==0)
    return 0;
    else
    return sum(x-1)+x;
    }
    以x=0为基准,和为0,无须经过递归,x逐渐向0靠拢

    展开全文
  • 1、递归必须有明确终止条件,不能一直递归不输出; 2、函数处理规模一定是递减 【不然,也是无法终止 要向终止条件 递归...//前面两个的和是后一个数 //求斐波那契数列第N个数 f(n) = f(n-1)+f(n-2) ////递归必须得

    1、递归必须有明确终止条件,不能一直递归不输出;
    2、函数处理规模一定是递减 【不然,也是无法终止 要向终止条件 递归前进】
    3、这个转化必须是可解的【这个问题可以递归解决 才能用递归 ,不然不要用递归】

    #include<iostream>
    #include<string>
    using namespace std;
    
    //1 2 3 5 8  13 21 34
    //前面两个的和是后一个数
    //求斐波那契数列第N个数  f(n) = f(n-1)+f(n-2)
    
    递归必须得有一个明确的终止条件
    //该函数所处理的数据规模必须在递减
    //这个转化必须是可解的
    int febonaqie(int n) {
    	if (n==1)
    	{
    		return 1;
    	}
    	else if (n==2)
    	{
    		return 2;
    	}
    	else
    	{
    		//用递归 f(n) = f(n-1)+f(n-2)
    	return febonaqie(n - 1) + febonaqie(n - 2);
    	}
    
    
    }
    
    
    int main() {
    
    	cout << febonaqie(7) << endl;
    
    }
    
    展开全文
  • 递归

    2019-02-18 10:15:17
    抓住两个要点:“相似性”和“出口” 没有相似性,主动构造 不相似的原因很有可能是缺少参数 类似数学公公式上的递推  《二》递归的调用 被调函数恰为主调函数 调用次序不同 递归的调用离不开栈,栈...

    目录

    《一》构造递归

    《二》递归的调用

    构造递归代码

    《三》递归和回溯

    更多代码

    《四》递归的局限性

     小结


    《一》构造递归

    抓住两个要点:“相似性”和“出口

    没有相似性,主动构造

    不相似的原因很有可能是缺少参数

    类似数学公公式上的递推 

    《二》递归的调用

    1. 被调函数恰为主调函数
    2. 调用次序不同
      • 递归的调用离不开栈,栈的作用是后进先出

      • 栈会保存断点的信息,待执行完被调函数之后返回主调函数从断点处继续执行

    3. 注意返回次序(后进先出)
    4. 形参并非同一变量
      1. 虽然传递的都是同一个参数,但他们本质上是不同的
      2. 比如:山上有个庙庙里有个老和尚这样的循环,老和尚所在的山是山1,他所讲的山是山2

    构造递归代码

    # include<cstdio>
    
    #if 0
    构造递归:
    先考虑共性函数,再对终止条件做限制 
    
    共性函数的设计不同,其递归函数的结构也不同 
    # endif
    
    //从begin打印到end 先打印begin(1) 
    void f(int begin,int end)
    {
    /*
    当发现递归没有共通性时,可以考虑增加参数 
    */	
    	if(begin > end)
    		return ;
    	printf("%d ",begin);
    	f(begin+1,end);
     } 
    
    //打印1~n  先打印9(从大到小打印) 
    void f2(int n){
    	if(n > 1)
    		f2(n-1);
    	printf("%d ",n);
    } 
    
    int main()
    {
    	int n = 9;
    	f(1,n);//打印0-n 
    	printf("\n"); 
    	f2(n);
    	
    	return 0;
     } 
     /*数组求和*/
    # include<cstdio>
    
    /*三种思路
     *(1)a[begin] + (a[begin+1]+...+a[end]) 
     *(2)(a[begin] + a[end-1]) + ... a[end]
     *(3)折半相加 
     */
     
    int length(int a[])
    {
    	int len = 0;
    	for(int i = 0;a[i];++i)
    		len++;
    	return len;
    }
     
    /*两种基本递归求和*/
    int f1(int a[],int begin)
    {
    	if(begin == length(a))
    		return 0;
    	int x = f1(a,begin+1);
    	return x + a[begin];
    }
    
    int f2(int a[],int end)
    {
    	if(end < 0)
    		return 0;
    	int x = f2(a,end-1);
    	return x + a[end];
    }
    
    /*折半相加*/
    int f3(int a[],int begin,int end)
    {
    	int mid = (begin+end)/2;
    	if(mid == end)
    		return a[end];
    	if(begin == mid)
    		return a[mid];
    	
    	return f3(a,begin,mid) + f3(a,mid,end);
     } 
    
    int main()
    {
    	int a[] = {2,5,8,9,6,3,1,4,7};
    	
    	int begin = 0;
    	//int sum1 = f1(a,begin);
    	//int sum2 = f2(a,length(a));
    	int sum3 = f3(a,begin,length(a)); 
    	printf("%d",sum3); 
    	
    	return 0;
     } 
    # include<iostream> 
    # include<string>
    
    using namespace std;
    
    /*判断两个串是否相等*/
    bool f(string& s1,string& s2){
    	if(s1.length() != s2.length())
    		return false;
    	if(s1.length() == 0)
    		return true;
    	
    	if(s1[0] != s2[0])
    		return false;
    	string ss1 = s1.substr(1,s1.length());
    	string ss2 = s2.substr(1,s2.length());
    	return f(ss1,ss2);
    }
    
    int main()
    {
    	string s1,s2;
    	
    	cout << "输入串1:" << endl;
    	getline(cin,s1);
    	cout << "输入串2:" << endl;
    	getline(cin,s2); 
    	
    	if(f(s1,s2))
    		cout << "相等!" << endl;
    	else
    		cout << "不相等!" << endl; 
    
    	return 0;
    }

    《三》递归和回溯

    注意:

    每一次调用都要降低计算规模

    找到相似性

    定义出口

    注意出口的顺序

    注意回溯

    回溯的作用就是保持单一变量

    回溯代码:

    # include<iostream>
    # include<algorithm>
    # include<string> 
    
    using namespace std;
    
    /*全排列递归算法 */
    #if 0
    相似性:
    字符串中的每一个字符都可以做第一位(遍历字符串中的每一个字符),确定当前一位,之后依次确定
    出口: 
    字符串中的每一个字符都放到过第一位 
    #endif 
    //k:记录当前交换位置 
    void f(string &s,int k){
    	if(k == s.length()){
    		for(int i = 0;i < s.length();++i)
    			cout << s[i] << " ";
    	
    		cout << endl;
    	}
    	
    	//循环遍历时,需要注意回溯 回归到原状态,来确保只有单一变量 
    	for(int i = k;i < s.length();++i)
    	{
    		int t = s[k]; s[k] = s[i]; s[i] = t;//交换
    		f(s,k+1);
    		t = s[k]; s[k] = s[i]; s[i] = t;//回溯 
    	 } 
    }
    
    int main()
    {
    	string str = "abc";
    	
    	f(str,0);
    
     return 0;
    }
    
    # include<iostream>
    # include<algorithm>
    # include<string>
    
    using namespace std;
    
    /*求最大公共子序列个数*/
    //递归
    
    /*
    相似性:
    s1的第一个字符和s2的字符
    {
    相等:截取两个串的第一个的串比较
    不相等:分别截取s1和s2的首字符求两个最大公共子串的最大值 
    } 
    
    出口:
    任一个子串的长度为0 
    */
    int f(string &s1,string &s2){
    	
    	if(s1.length() == 0 || s2.length() == 0)
    		 return 0;
    	
    	string ss1 = s1.substr(1,s1.length());
    	string ss2 = s2.substr(1,s2.length());
    	if(s1.at(0) == s2.at(0))
    		return f(ss1,ss2)+1;
    	else
    		return max(f(ss1,s2),f(s1,ss2));
    } 
    
    int main()
    {
    	string s1,s2;
    	
    	getline(cin,s1);
    	getline(cin,s2);
    	
    	cout << f(s1,s2); 
    	
     return 0;
    }
    

    更多代码

    # include<iostream>
    # include<algorithm> 
    
    using namespace std;
    
    /*递归解法 
    相似性: 
    思路就是从n个球中选一个特殊的,要么选【f(n-1,m-1)】,要么不选【f(n-1,m)】
    出口:
    n < m     --> 0 
    n == m    --> 1
    m == 0    -->1
    */
    long long f(int n,int m){
    	if(n < m)
    		return 0;
    	if(n == m)
    		return 1;
    	if(m == 0)
    		return 1;
    	
    	return f(n-1,m-1) + f(n-1,m);
    }
    
    /*优化算法*/
    long long f1(int n,int m){
    	
    }
    
    int main()
    {
    	cout << f(3000,3) << endl;
    
     return 0;
    }

    # include<iostream>
    # include<algorithm>
    # include<string> 
    
    using namespace std;
    
    /*字符串反转递归实现*/
    string reverse(string &s){
    	if(s.length() < 2) return s;
    	string ss = s.substr(1,s.length());
    	return reverse(ss) + s.at(0);
    }
    
    int main()
    {
    	string s;
    	
    	cin >> s;
    	cout << reverse(s) << endl;
    
     return 0;
    }
    
    # include<iostream>
    # include<algorithm>
    
    using namespace std;
    
    #if 0
    杨辉三角可以转化成下三角矩阵的形式 
    		 1                 1
    	   1   1               1  1
    	  1  2  1              1  2  1
    	 1  3  3  1       ===> 1  3  3  1
    	1  4  6  4  1          1  4  6  4  1
       1  5 10 10  5 1	       1  5 10 10  5  1
    # endif
    
    //输出杨辉三角的第m层第n个元素的系数
    int f(int m,int n){
    	if(m == 0 || n == 0) return 1;
    	if(n == m) return 1;
    	return f(m-1,n) + f(m-1,n-1); 
    } 
    
    int main()
    {
    	int m;
    
    	cout << "输入杨辉三角的层数:";
    	cin >> m;
    	m -= 1;	
    	for(int i = 0;i <= m;++i)
    		cout << f(m,i) << " "; 
    
     return 0;
    }
    
    # include<iostream>
    # include<algorithm>
    
    using namespace std;
    
    int n = 5;
    
    /*计算错误和*/
    //err_sum:错误和
    //a[]:数组 
    //k:当前项 
    //cur_sum:当前和 
    //b[]:是否取当前项 
    void f(int err_sum,int a[],int k,int cur_sum,bool b[]){
    	
    	if(cur_sum > err_sum)	return ;
    	if(cur_sum == err_sum){
    		for(int i = 0;i < n;++i)
    			if(b[i])
    				cout << a[i] << " ";
    		cout << endl;
    		return ;
    	}
    	if(k >= n)	return ;
    	
    	//分两种情况:是否取当前项 
    	b[k] = false;
    	f(err_sum,a,k+1,cur_sum,b);
    	
    	b[k] = true;
    	cur_sum += a[k];
    	f(err_sum,a,k+1,cur_sum,b);
    	b[k] = false;
    }
    
    int main()
    {
    	int err_sum = 6;
    	
    	int a[] = {3,2,4,3,1};
    	bool *b = new bool[n];
    	
    	for(int i = 0;i < n;++i)
    		b[i] = false;
    	f(err_sum,a,0,0,b); 
    
     return 0;
    }
    

     《四》递归的局限性

    一、函数调用需要使用内存中的栈来保存函数的数据以及访问链和控制链,如果数据是必须的,那么访问链和控制链等所占的内存则是额外的。
    二、使用递归,会进行很深层次的调用函数,所以需要调用很多函数,需要建立许多的访问链和控制链,占用大量内存,而且调用时传递参数,申请空间,返回时恢复现场,都有时间的花销,所以递归效率低。
    三、内存的栈当作一个容器,每次递归,函数都往容器中添加容量,当添到一定层次,容器满了,就溢出了,如果用递归,如果忘记了递归截至条件,你就可能进入了无穷递归,无穷递归必然会溢出,所以,不提倡递归。


     小结

    递归算法一般都是提供一种思路,对于规模较小可以解决,但远远不能满足正常规模的输入(如组合问题中,才3000就需要30多秒,这已经算挂了),所以常常需要优化算法。

    部分优化算法:

    斐波拉切数列及优化:https://blog.csdn.net/qq_40479037/article/details/87518265

    阶乘计算及优化:https://blog.csdn.net/qq_40479037/article/details/87522118

    展开全文
  • 递归的本质

    2020-04-19 22:00:36
    确定了一个问题是递归问题后,递归其实就两个要点:结束条件、子问题解法。 同时还有两个要注意地方:从上至下分析剥开并解决、复杂度 今天看到了两张醍醐灌顶图,记录一下 递归应用太广泛了,实例也没啥...

    确定了一个问题是递归问题后,递归其实就两个要点:结束条件、子问题解法。
    同时还有两个要注意的地方:从上至下的分析剥开并解决、复杂度

    今天看到了两张醍醐灌顶的图,记录一下
    在这里插入图片描述

    在这里插入图片描述

    递归应用太广泛了,实例也没啥好些的,经典例子就那些,以后遇到特别的再补充吧

    在这里插入图片描述

    ↑路径压缩里面的假递归(系统会自动转为循环)是真牛批

    展开全文
  • 递归的深入理解

    2020-01-21 17:10:59
    图是单路径递归(最基础的递归),以下三例题是每一步分条路径递归(其实也是先递归一条,回溯后再递归另一条,但是可以看作条路径同时进行) 补充:递归和回溯法联系 1. 递归是一种算法结构,回溯...
  • 递归的理解的要点主要在于放弃!放弃你对于理解和跟踪递归全程的企图,只理解递归层之间的交接,以及递归终结的条件。 想象你来到某个热带丛林,意外发现了十层之高的汉诺塔。正当你苦苦思索如何搬动它时,林中...
  • 抓住递归的两个要点: 1. 找到相似性。必须寻找到本问题和子问题的相似性,即:仅仅表现为同一过程的不同参数的现象。 2. 递归不要忘记了设计出口。递归必须在某个时候停止,不能无休止调用下去。
  • 理解递归

    2021-01-13 14:51:05
    递归包含两个过程:向下调用和向上返回 计算机通过函数调用栈,逐层向下调用,到达递归出口后,再逐层向上返回,即 call 和 return 指令实现递归 理解递归有几个要点 原问题可以分解为相似更小子问题,子...
  • 递归的个要点: 终止条件,递归应该在什么条件终止? 返回值,当前应该给上一级返回什么? 递归方法,在这一级递归中,应该完成什么任务? 例1: 将两个有序链表合并为一个新的有序链表并返回。新链表是...
  • 递归算法

    2017-12-25 13:06:01
    1.什么是递归算法  任何调用自身函数称为递归。用递归算法求解问题,要点在于递归函数调用自身去解决一个规模比原始问题小一些问题。这个过程成为递归步骤。递归算法执行递归步骤... 递归算法有两个要点,当编写
  • 循环改递归的两要点 发现逻辑循环中的**“相似性”** 找到递归的**“出口”** 确定递归的参数 踢皮球思想理解递归 “踢皮球”-常用来形容政府职能部门职责不清,相互推诿,比如你要到部门A盖章,A叫你先去部门...
  • 二、递归条件采用递归方法来解决问题,必须符合以下三条件:1、可以把要解决问题转化为一新问题,而这问题解决方法仍与原来解决方法相同,只是所处理对象有规律地递增或递减。说明:解决问题...
  • 递归的理解的要点主要在于放弃!放弃你对于理解和跟踪递归全程的企图,只理解递归层之间的交接,以及递归终结的条件。想象你来到某个热带丛林,意外发现了十层之高的汉诺塔。正当你苦苦思索如何搬动它时,林中...
  • 递归模型

    千次阅读 2018-02-22 13:21:23
    递归的理解的要点主要在于放弃! 放弃你对于理解和跟踪递归全程的企图,只理解递归层之间的交接,以及递归终结的条件。(知乎-Fireman A) 一、递归的定义 从前有座山,山里有座庙,庙里有老和尚,...
  • 递归的理解的要点主要在于放弃!放弃你对于理解和跟踪递归全程的企图,只理解递归层之间的交接,以及递归终结的条件。想象你来到某个热带丛林,意外发现了十层之高的汉诺塔​。正当你苦苦思索如何搬动它时,林中...
  • 递归函数

    2018-09-15 07:00:46
    递归法,就是把原问题简化,并套用解决原问题时思路,来解决简化之后问题,这简化并套用步骤就称为递归步骤。。 递归的要点在于必须确保整个递归过程能够终止,换言之就是说,每次调用所要解决问题,要...
  • 反转一个单链表-递归实现 示例 输入: 1->2->3->4->5->NULL 输出: 5->4->...使用递归方式实现 因为要将所有节点...递归时有两个要点 将所有node压入栈时候,一定要有一个边界条件 在node出...
  • 一、基本内容:  C语言中函数可以递归调用,即:可以直接(简单递归)或间接(间接递归)地自己调自己。  要点: ... 1、可以把要解决问题转化为一新问题,而这问题解决方法仍
  •  采用递归方法来解决问题,必须符合以下三条件: 1、可以把要解决问题转化为一新问题,而这问题解决方法仍与原来解决方法相同,只是所处理对象有规律地递增或递减。 说明:解决问题方法相同...
  • 递归详解

    2019-03-10 14:48:20
    通俗解释 递归:就是函数自己调用自己。 优势 递归知识让结局方案更清晰,并没有性能上优势。...正因为如此,每个递归都有部分: 基线条件和递归条件。 递归条件: 函数继续调用自己 基线条件:函数不在调用自己...
  • 一、二叉树的的遍历 构建二叉树数据结构 class BinaryTree{ int val; BinaryTree left; BinaryTree right; public BinaryTree(int val){ ...**构建递归时有两个要点需要特别注意,一是递归...
  • 一、基本内容: C语言中函数可以递归... 二、递归条件 采用递归方法来解决问题,必须符合以下三条件: 1、可以把要解决问题转化为一新问题,而这问题解决方法仍与原来解决方法相同,只是所处理...
  • 简介查找是很常见操作,一般就循环遍历,不过如果数据量大...虽然代码不难,但是也有几个要点需要注意: 取中值 如果直接mid = ( low + high )/2; 这样一般没什么错,但是要考虑数据量很大时就容易整数溢出。 所以
  • 递归自我总结

    2021-05-17 21:09:04
    递归 概念 什么是递归? 在一函数的内部执行 **自身** ...提示:如要用递归进行相关的编程那么一定要进行要点的寻找要点有如下点 一递归的相关公式 一递归的终点 找到两者之后进行相关的计算 注意
  • 递归和循环迭代

    2019-10-25 19:21:15
    递归包含两个要点,一个是递归方式,一个是函数出口(即问题最小规模),然后逐层次解决问题。递归和循环在某些方面是差不多,比如递归要重复调用本身。在大多数情况下,递归比循环更耗费时间和空间,然而...
  • java递归学习

    2021-04-19 11:03:21
    概要:递归是一种编程思想和...下面结合两个实例:斐波那契数列和汉诺牌 public class TestFebonacci { public static void main(String[] args) { //斐波那契数列:1 1 2 3 5 8 13 int i = febonacci(7); S.
  • 函数的递归和调用

    2008-10-03 00:59:00
    一、基本内容: C/C++语言中函数可以递归调用,即:可以直接(简单... 二、递归条件 采用递归方法来解决问题,必须符合以下三条件: 1、可以把要解决问题转化为一新问题,而这问题解决方法仍与原来
  • C语言函数的递归和调用

    千次阅读 2013-03-13 01:17:42
     C语言中函数可以递归调用,即:可以直接(简单递归)或间接(间接递归)地自己调自己。     要点:  1、C语言函数可以递归调用。  2、可以通过直接或间接种方式调用。目前只讨论直接递归调用。  二...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 244
精华内容 97
关键字:

递归的两个要点