递归小论(2)

2023-11-11 06:58
文章标签 递归 小论

本文主要是介绍递归小论(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

请扫码加公众号大笑



上次简单介绍了一下什么是递归,这一次来说说递归的难点作用

 

 

不记得上次是否有说过,递归是一个衡量程序员是否成熟的标识。

 

然而我到现在在递归上做得最远的也仅仅是把插入排序二分搜索之类的改成递归写法,其余啥都没有,所以水平有限。

 

因为递归真的是嗨难嗨难。

 

 

递归难点1:在解决问题的时候把大问题改造成一个小问题(开始难)

上次有提到过分治法。分治,分治,分在先,治在后。

然而,分这个过程是很难决定的。

 

二分搜索啊,归并排序啊这些都还算正常的思路,毕竟一半一半的考虑是人类思考一种普遍方式。

 

这种一半一半的分布源于在于往往人们会把分布想象成均匀分布.

 

然而,糟糕的事情在于,问题空间往往并不是均匀分布的,就想在自然界中最普遍的分布并不是均匀分布,而是用起来极其麻烦并且还是连续的正态分布。

 

矩阵的乘法一直是计算机内很难解决的效率问题,因为到现在高效的算法效率才达到N^(lg7)也就是在N^(2. 8)左右(Strassen算法),也就是说比最慢的插入排序还慢。然而,为了减少这0.2次的效率,算法在处理矩阵的把原问题化为了7个子问题。7个,7个子问题,想着7个子问题得耗费多少心血(说实在的,我到现在都没想出创始人是怎么想出7等分这样精分的分解方法)

 

所以,问题空间并不均匀造成分解这一步往往就会遇到困难。

(事实上,在递归入门的时候最经典的两个一个就是汉诺塔,一个就是阶乘。阶乘尚且容易理解,也容易写出来。然而汉诺塔,我觉得能把问题往递归方面想,太难了……)

 

递归难点2:递归的底层是什么(中间难)

不同的分解方式会造成最终计算机停止的地方不同,就如阶乘,计算机会停留在N=0的情况,这是非常确定的。

 

然而,随着分解的方法不断复杂,递归底层变得并不容易那么确定。

 

递归底层可能有两种情况比如N=0,N=-1

递归底层还有可能是left>right

递归底层还有可能是NULL=object

 

如果分解方法简单,最后的底层往往就是一个,然而简单的分解结构就是效率的低下,甚至出现用递归还不如不用的情况(比如阶乘的例子被人嘲笑诟病了很久很久)

 

最麻烦的是,有时候你根本就很难猜到底层是啥……

为什么? 因为有一种技术叫随机化……(获得概率上期望最佳也就是平均效率最后,将要讲的随机化快速排序即是如此)

当把算法随机化以后,所有的事情全靠运气了   为人事,尽天命吧。

 

 

递归难点2:合并算法(最后,还是,难)

当想出一些天马行空无厘头的分解方法以后,计算机也就会帮你一路走到底直接走到并不一定知道的递归的底层,然后也就停下来了。

 

这蠢机器并不知道怎样从底层走回原来最开始的调用……

 

所以这时候就要设计算法把底层合并起来解决(其实并不是简单的底层合并,而是类似1并2, 2并4 , 4并8 这样的滚雪球解决,所以合并算法还要考虑到规模问题……)

 

之前有说过归并排序的合并算法,那个算法说实话还不算复杂,但是作为一个算法来说,代码长度并不短(可能是我写的不好)

 

糟糕的是,归并排序的合并算法是一个比较轻松的合并算法……

 

因为篇幅问题,合并算法的难点直接列出来吧,如果有兴趣可以后台留言,下次我在详细说明

合并算法必须知道底层是怎么样的

合并算法必须得根据回归过程对数据操作改变规模

合并算法在时间问题上必须要最小,如果它慢,整个算法不可能快,它是决定算法快慢的灵魂(也是递归的灵魂)

合并算法还得会处理两个不同规模的数据(比如一个数据有7个元素,另一个数据有100个元素),不同规模数据出现是经常发生的

 

综上而述,递归开头难,中间难,最后还是难。

 

 

但是,调用递归简单呀,比如你有一个aRecursion()函数,怎样递归呢

aRecursion()

{

 

    statement

    aRecursion()

}

这篇关于递归小论(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/388313

相关文章

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT

oracle11.2g递归查询(树形结构查询)

转自: 一 二 简单语法介绍 一、树型表结构:节点ID 上级ID 节点名称二、公式: select 节点ID,节点名称,levelfrom 表connect by prior 节点ID=上级节点IDstart with 上级节点ID=节点值 oracle官网解说 开发人员:SQL 递归: 在 Oracle Database 11g 第 2 版中查询层次结构数据的快速

Leetcode面试经典150题-128.最长连续序列-递归版本另解

之前写过一篇这个题的,但是可能代码比较复杂,这回来个简洁版的,这个是递归版本 可以看看之前的版本,两个版本面试用哪个都保过 解法都在代码里,不懂就留言或者私信 class Solution {/**对于之前的解法,我现在提供一共更优的解,但是这种可能会比较难懂一些(思想方面)代码其实是很简洁的,总体思想如下:不需要排序直接把所有数放入map,map的key是当前数字,value是当前数开始的

【UVA】10651-Pebble Solitaire(直接递归或者记忆化)

不知道这个题UVA的数据是怎么的,用2个方法交了,第一次直接递归,第二次记忆化剪枝,时间竟然一样!? 直接郁闷了,简单的二进制表示状态和二进制运算。 14145176 10651 Pebble Solitaire Accepted C++ 0.009 2014-09-04 09:18:21 #include<cstdio>#include<algorithm>#inclu

笔试强训,[NOIP2002普及组]过河卒牛客.游游的水果大礼包牛客.买卖股票的最好时机(二)二叉树非递归前序遍历

目录 [NOIP2002普及组]过河卒 牛客.游游的水果大礼包 牛客.买卖股票的最好时机(二) 二叉树非递归前序遍历 [NOIP2002普及组]过河卒 题里面给的提示很有用,那个马的关系,后面就注意,dp需要作为long的类型。 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息publ

HCIA--实验十:路由的递归特性

递归路由的理解 一、实验内容 1.需求/要求: 使用4台路由器,在AR1和AR4上分别配置一个LOOPBACK接口,根据路由的递归特性,写一系列的静态路由实现让1.1.1.1和4.4.4.4的双向通信。 二、实验过程 1.拓扑图: 2.步骤: (下列命令行可以直接复制在ensp) 1.如拓扑图所示,配置各路由器的基本信息: 各接口的ip地址及子网掩码,给AR1和AR4分别配置

Winform中在窗体中的Paint事件中重绘会导致递归问题?

在 WinForms 应用程序中,如果在窗体的 Paint 事件处理程序中不断调用 Invalidate 方法,确实可能会导致递归调用的问题。这是因为每次调用 Invalidate 方法时,都会向消息队列添加一个绘制消息,当消息队列中的绘制消息被处理时,会触发 Paint 事件。如果 Paint 事件处理程序中又调用了 Invalidate,就会形成一个循环,导致递归调用 Paint 事件,这

每日OJ_牛客_求和(递归深搜)

目录 牛客_求和(递归深搜) 解析代码 牛客_求和(递归深搜) 求和_好未来笔试题_牛客网 解析代码         递归中每次累加一个新的数,如果累加和大于等于目标,结束递归。此时如果累加和正好等于目标,则打印组合。向上回退搜索其它组合。此题本身就是一个搜索的过程,找到所有的组合。 #include <iostream>#include <cmath>#in

归并排序-非递归实现

归并排序的非递归实现  我们可以把 一个数组 先拆分成 最小单元,这是分, 拆分成最小单元之后,我们对每个最小单元进行一次合并,这是治 最小单元 合并一次之后,我们继续 在上一次合并的基础上拆分,并且合并这是 合 , 直到 整个数组 只被拆成了两部分,在进行最终一次的和   我们画图举个例子 源代码如下,我们的merge的合并函数的参数是  原数组,左侧小数组索引位置开头,左侧小数

力扣 | 递归 | 区间上的动态规划 | 486. 预测赢家

文章目录 一、递归二、区间动态规划 LeetCode:486. 预测赢家 一、递归 注意到本题数据范围为 1 < = n < = 20 1<=n<=20 1<=n<=20,因此可以使用递归枚举选择方式,时间复杂度为 2 20 = 1024 ∗ 1024 = 1048576 = 1.05 × 1 0 6 2^{20} = 1024*1024=1048576=1.05 × 10^