在尝试为另一个SO问题写一个答案的时候发生了一件非常奇怪的事情.
我基本上想出了一个内置gcd并说 it maybe slower because of recursion
gcd = lambda a,b : a if not b else gcd(b, a % b)
这是一个简单的测试:
assert gcd(10, 3) == 1 and gcd(21, 7) == 7 and gcd(100, 1000) == 100
Run Code Online (Sandbox Code Playgroud)
这里有一些基准:
timeit.Timer('gcd(2**2048, 2**2048+123)', setup = 'from fractions import gcd').repeat(3, 100)
# [0.0022919178009033203, 0.0016410350799560547, 0.0016489028930664062]
timeit.Timer('gcd(2**2048, 2**2048+123)', setup = 'gcd = lambda a,b : a if not b else gcd(b, a % b)').repeat(3, 100)
# [0.0020480155944824219, 0.0016460418701171875, 0.0014090538024902344]
Run Code Online (Sandbox Code Playgroud)
那很有意思,我预计会慢很多,但时间相当接近,?也许导入模块是问题...
>>> setup = ''' …Run Code Online (Sandbox Code Playgroud) 我有一个计算任何数字的阶乘的程序.当我尝试将其作为100,000这样的大数字时,它会在它达到0之前停止.我猜这是一种防止出现问题的安全机制.
虽然这很好,但它可以防止程序计算大量数字.在我的程序中,变量x达到0后,它会停止递归函数.所以不需要这个"安全网".
这是我的代码供参考:
#include <iostream>
#include <string>
int answer = 1;
int recursive(int x);
using std::cout;
using std::cin;
int main() {
recursive( 100000 );
}
int recursive( int x ) {
cout << x << "\n";
answer = x * answer;
x--;
if ( x > 0 ) {
recursive( x );
}
else {
cout << "Answer: " << answer << "\n";
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法解决这个障碍?
我知道在这个SO答案中写出的尾递归算法是什么.然而,我正在通过麻省理工学院的快速排序算法视频,并在18:30秒教授说这是尾递归算法.我无法连接这是如何尾递归.我们不是在递归的任何步骤进行计算,还是我们?你能解释为什么这被引用作尾递归算法的一个例子.请以我知道递归算法是什么为前提,给出答案.我不清楚的部分是为什么它被称为尾递归?
algorithm complexity-theory tail-recursion quicksort time-complexity
的空间复杂度Quicksort为。 O(logn)
然而 -Quicksort可以在不使用任何额外内存的情况下进行处理:在每次迭代时,在分区过程中,条目最终会根据所使用的主元交换到左分区和右分区中。这种递归交换并由此形成分区可以在列表本身上完成,而不会在一级递归调用中存在分区干扰,并且不会在不同级别的调用中进行快速排序干扰。
额外的内存有什么用Quicksort?
TIA。
//============================
编辑:
同意评论/答案中的堆栈空间——错过了这一点。
仍然,
O(nlogn)快速排序在预期情况下及时执行——通过在每个递归级别形成(几乎)相同大小的分区。
使用的堆栈空间是二叉树,在最佳情况下是完整的树,高度为log n。该树上的每个节点都是递归调用,本例中的堆栈空间约为n-- not log n。有O(n)这棵树上对左右分区的递归调用是同时进行的——调用树在某个执行点已满。
所以-平均情况空间复杂度应该是O(n)--不是O(logn)(?)
它也与归并排序的空间复杂度相矛盾。合并排序空间复杂度被列出为O(n)并且处理类似。
sorting algorithm complexity-theory quicksort data-structures
我一直在尝试用F#编写一个程序,它接受两个值(一个元组):一个数字和一个字符串.根据字符串是否告诉程序添加或乘法,它将使用从1到该数字的所有整数(即1..n)添加或乘以输入数字.
这是代码
let addormult (n:int, what:string) =
if what = "multiply" then
let rec product n =
if n<1 then 0
else n*product(n-1)
printfn "%A" product
elif what = "sum" then
let rec sum =
if n<1 then 0
else n + sum(n-1)
printfn "%A" sum
Run Code Online (Sandbox Code Playgroud)
但是,每次我尝试运行此功能时,都会收到错误消息
"这个值不是一个功能,不能应用."
那么我做错了什么?
在我的大学里,我被要求为Fibonacci系列写一个JAVA程序.我使用递归来编写该程序.
但是,助理讲师说我的算法效率不高,并要求我分析.他补充说,按照惯例,迭代适用于该程序而不是递归.
如何分析我们的算法?如何在迭代和递归中检查空间和时间复杂度?就在这时,我发现这些东西和程序的正确性一样重要.
我有一个清单 ['','','',['',[['a','b']['c']]],[[['a','b'],['c']]],[[['d']]]]
我想用索引展平列表,输出应如下所示:
flat list=['','','','','a','b','c','a','b','c','d']
indices=[0,1,2,3,3,3,3,4,4,4,5]
Run Code Online (Sandbox Code Playgroud)
这该怎么做?
我已经试过了:
def flat(nums):
res = []
index = []
for i in range(len(nums)):
if isinstance(nums[i], list):
res.extend(nums[i])
index.extend([i]*len(nums[i]))
else:
res.append(nums[i])
index.append(i)
return res,index
Run Code Online (Sandbox Code Playgroud)
但这不能按预期工作。
以下是我的示例代码:
def test(v)
test(v-1) if v > 0
p v
end
Run Code Online (Sandbox Code Playgroud)
如果我打电话test(11893)它工作正常.如果我有v > 11893,那就是扔SystemStackError.如何增加此错误的限制?
我一直在读几个人们选择使用Stack而不是递归的地方.这是因为递归被认为是完成工作的过时方式,或者这两种方法在不同的环境中同样适用吗?
在我的练习中,我必须决定函数是什么类型的递归。
我们必须从线性递归、尾递归和保护递归中进行选择,但我不太明白后两者之间的区别。
有人可以解释一下保护递归和尾递归之间的区别吗?
我们要区分的功能供参考:
pow2 0 = 1
pow2 n = 2 * pow2 (n-1)
factAux r i n
| i <= n = factAux (i * r) (i + 1) n | otherwise = r
factorial = factAux 1 1
init [x] = []
init (x:xs) = x : init xs
binom n 0 = 1
binom n k
| n == k = 1
| otherwise = binom (n - 1) k + binom (n - 1) (k …Run Code Online (Sandbox Code Playgroud)