chapter_computational_complexity/iteration_and_recursion/ #694
Replies: 127 comments 167 replies
-
我算法小白理解的递归和尾递归,递归就好像是拿着个小本本,算一次,算不出答案,需要标记一下继续算,一直到最后一个答案算出来再根据标记往回总结答案,而尾递归则是算一次更新一下答案,所以到最后答案可以直接得出,这样的话感觉跟迭代很像啊 |
Beta Was this translation helpful? Give feedback.
-
简单查了一下好像支持尾递归优化的语言不多,相对主流一些的语言 Java、Python、Go 之类的都不支持。 |
Beta Was this translation helpful? Give feedback.
-
f(n),f是什么意思 |
Beta Was this translation helpful? Give feedback.
-
希望添加迭代器的代码 |
Beta Was this translation helpful? Give feedback.
-
我愿称之为最强教程。这一章终于完全理解了迭代和递归的不同,终于完全理解了尾递归。豁然开朗的爽感让我继续如饥似渴地阅读下面的内容! |
Beta Was this translation helpful? Give feedback.
-
很多语言没有对尾递归进行优化,数据量不确定的情况下,用递归风险岂不是很大 |
Beta Was this translation helpful? Give feedback.
-
开头第一段话因为我不是很懂,所以去问了一下GPT,回复说:“迭代和递归都是程序中常见的控制结构,而不是程序结构本身。”这个回答是正确的吗?以及控制结构和程序结构的同异是什么呢?🤔 |
Beta Was this translation helpful? Give feedback.
-
比作挖坑的话 然后迭代解题关键就是计算好每次挖多少,迭代每次挖的土都是固定的重量,最后只管算挖了几次就能知道。 迭代跟递归配合就是 在原地挖坑?不用往前走也不用去下一层 直接原地计算?有点迷糊了。 int fibonacci(int n) {
if (n <= 0) {
return 0;
}
if (n == 1) {
return 1;
}
int prev = 0; // 第一个斐波那契数
int current = 1; // 第二个斐波那契数
int result = 0; // 存储计算的结果
for (int i = 2; i <= n; ++i) {
result = prev + current;
prev = current;
current = result;
}
return result;
} chatgpt的迭代加递归 原地搞三个坑prev current result |
Beta Was this translation helpful? Give feedback.
-
例如在以下代码中,条件变量,每轮进行了两次更新,这种情况就不太方便用 for 循环实现。 /* while 循环(两次更新) */
int whileLoopII(int n) {
int res = 0;
int i = 1; // 初始化条件变量
// 循环求和 1, 4, ...
while (i <= n) {
res += i;
// 更新条件变量
i++;
i *= 2;
}
return res;
} 这个地方提到用for循环不好实现,可是 int res = 0;
for (int i1 = 1; i1 <= n; ) {
res += i1;
i1++;
i1 *= 2;
} 这样写也一样能实现的,感觉和while没啥大的区别 |
Beta Was this translation helpful? Give feedback.
-
分治是一种算法设计思想,它通过将问题划分为多个相同或相似子问题,并分别解决这些子问题,最后将子问题的解合并起来得到原始问题的解。分治思想通常包括三个步骤:分解、解决和合并。
分治思想通常用于解决问题的规模较大、复杂度较高的情况,它可以将原问题划分为多个较小的子问题,从而简化原问题的求解过程。常见的应用包括归并排序、快速排序、二分搜索等。通过分治思想,可以提高算法的效率和可扩展性。分治是一种算法设计思想,它通过将问题划分为多个相同或相似子问题,并分别解决这些子问题,最后将子问题的解合并起来得到原始问题的解。分治思想通常包括三个步骤:分解、解决和合并。
分治思想通常用于解决问题的规模较大、复杂度较高的情况,它可以将原问题划分为多个较小的子问题,从而简化原问题的求解过程。常见的应用包括归并排序、快速排序、二分搜索等。通过分治思想,可以提高算法的效率和可扩展性。 |
Beta Was this translation helpful? Give feedback.
-
”普通递归:当函数返回到上一层级的函数后,需要继续执行代码,因此系统需要保存上一层调用的上下文。” |
Beta Was this translation helpful? Give feedback.
-
C#的命名有点不友好, |
Beta Was this translation helpful? Give feedback.
-
问在for循环中什么c++里面是++i,c中就是i++ |
Beta Was this translation helpful? Give feedback.
-
请问,我用 print(fib(4)); 运行得到的结果是2,这和理解上的不一致,在本本上演算也是2,请问是哪里做的不对吗? |
Beta Was this translation helpful? Give feedback.
-
从这节开始明显变难了,想要理解得下功夫。我一年前被递归搞得遍体鳞伤,没想到一年后还是不咋样😂 |
Beta Was this translation helpful? Give feedback.
-
分享一下【递归】这块我的学习心得,之前也在别的书上看过,看的时时候感觉懂了,事后不是忘了就是遇到具体问题时不会用,说明没有掌握其精髓,这里我已文中最开始的示例举另一种例子帮助新手理解,作者文中给的是1到5的等差数列相加,例子使用了一个recur(5)的函数来演示,该函数只有一个参数,设计的很巧妙,但新手可能不太好理解这种巧妙。这里我降低难度换另一种思路帮新手理解:要计算1到5的等差数列之和,我们很容易受到题目要求的影响,潜意识认为应该设计一个函数recur(a,b),并在实际调用时使用recur(1,5)的方式去调用,这种思路当然可以,我们就按这个思路去设计。递归讲究的是把复杂问题分解为简单问题来解决,所以我们要先利用这个思想,1+2+3+4+5我可能不会算,但1+2我会,2+3我会,3+4我也会,总之就是我会最简单的2个数相加,那就好办了,我们把1+2+3+4+5尽可能的简化为2个数相加的模式,然后我们通过观察会发现开始的第一步一定是1+2,最后一步是4+5,当然也可以反过来倒着算5+4+3+2+1,不论正算反算,最后都是2个数相加,并且两个数之间相差1(例如1+2种的1和2,以及4+5中的4和5),这样我们现在知道的中止递归的条件,那就是当两个数相减相差1的时候就是“递转归”的时机。于是有以下代码,该代码不仅可以计算1到5的等差数列之和,也可以计算其他类型等差数列之和,比如2到6,具体代码如下: def recur(a, b):
if b - a == 1:
return a + b
res = recur(a + 1, b)
return res + a
c = recur(1, 5)
print(c) 最后我想对新手说的是,要想真正自己掌握递归,出了要记作者文中住递归用法的三个要素,更要自己动手去解一些递归小题目,不要一上来看答案,先尝试自己设计一下,会更容易让你理解递归! |
Beta Was this translation helpful? Give feedback.
-
def fib(n:int)->int: print(fib(5)) number is 1 |
Beta Was this translation helpful? Give feedback.
-
3.嵌套循环里的c代码strncat(res, tmp, size - strlen(res) - 1);,参数"size - strlen(res) - 1"是不是传错了 |
Beta Was this translation helpful? Give feedback.
-
斐波那契数列上面的代码有点难懂,改成我这个就容易理解一些 |
Beta Was this translation helpful? Give feedback.
-
如果归的部分是这样 return function(x-1) * x; 这算尾递归吗?return function(x-1) * 5这样呢 |
Beta Was this translation helpful? Give feedback.
-
我一直觉得尾递归这个名字很具有迷惑性,我说一下我看了一些博客对尾递归的理解。
尾递归在形式上是自我调用,但是在计算上是迭代,一步一步完成计算,归的过程只是返回结果。 |
Beta Was this translation helpful? Give feedback.
-
这里开始,就要认真琢磨了;可能需要看很久才可以理清楚 |
Beta Was this translation helpful? Give feedback.
-
我是不是太蠢了,自学了一轮python的基础代码之后来看这里感觉有点束手无策,自己着手复现出来代码也感觉有点困难 |
Beta Was this translation helpful? Give feedback.
-
浅谈一下尾递归和普通递归的区别
先说结论:主要区别就是看递归调用后,是否还有局部变量参与计算。 /* 普通递归 */
int recur(int n) {
// 终止条件
if (n == 1)
return 1;
// 递:递归调用
int res = recur(n - 1);
// 归:返回结果
return n + res;
// ↑↑↑↑↑↑↑以上为原文中代码,下面的为修改后的代码
// 上面两行代码和以下代码效果相同,
// return n + recur(n - 1);
} 先看上面普通递归的代码,在执行了递归方法后,生成了一个局部变量 res, 同时方法参数 n 也为局部变量。因为需要局部变量参与运算,所以方法不能弹栈,得保存栈帧信息,才能让递归方法在返回后拿到局部变量做进一步计算,即原文中的“上下文”。 将原文中的最后两行代码改为 /* 尾递归 */
int tailRecur(int n, int res) {
// 终止条件
if (n == 0)
return res;
// 尾递归调用
return tailRecur(n - 1, res + n);
} 再看尾递归的代码, 在 |
Beta Was this translation helpful? Give feedback.
-
小白问一嘴,为啥什么不在递归的时候使用一个列表储存前面的函数结果最后直接相加呢,这样就可以及时释放内存了 |
Beta Was this translation helpful? Give feedback.
-
如果递归函数返回类型是 |
Beta Was this translation helpful? Give feedback.
-
/* 尾递归 / 更直接的方法就是看有没有直接参与运算。 不知道理解对不对。 |
Beta Was this translation helpful? Give feedback.
-
javascript的运行环境也没有做尾递归优化,小心爆栈。 |
Beta Was this translation helpful? Give feedback.
-
小白 不知道我理解的有没有错误:尾递归 就是在调用自身的同时,计算出当前调用层的结果,并且一起传递。这样 归 的时候 直接返回结果值。但是要返回n次 |
Beta Was this translation helpful? Give feedback.
-
chapter_computational_complexity/iteration_and_recursion/
动画图解、一键运行的数据结构与算法教程
https://www.hello-algo.com/chapter_computational_complexity/iteration_and_recursion/
Beta Was this translation helpful? Give feedback.
All reactions