似乎所有的算法教科书都没有提及太空效率,所以当我遇到需要一个只需要恒定记忆的算法的问题时,我真的不明白。
使用常量内存和不使用常量内存的算法的几个算法示例会是什么?
答案 0 :(得分:5)
如果是算法:
a)递归多个深度,取决于N或
b)分配一定量的内存,这取决于N
然后它不是恒定的记忆。否则它可能是:正式地,如果算法使用的内存量有一个恒定的上限,无论输入的大小/值是多少,它都是常量内存。输入所占用的内存不包括在内,所以有时候要清楚你要谈论恒定的“额外”内存。
所以,这是一个常量内存算法,用于在C中查找整数数组的最大值:
int max(int *start, int *end) {
int result = INT_MIN;
while (start != end) {
if (*start > result) result = *start;
++start;
}
return result;
}
这是一种非常量内存算法,因为它使用与输入数组中元素数量成比例的堆栈空间。但是,如果编译器能够以某种方式将其优化为非递归等价物(C编译器通常不会烦恼,除非有时使用尾调用优化,它可能会成为常量内存,这在这里不起作用) ):
int max(int *start, int *end) {
if (start == end) return INT_MIN;
int tail = max(start+1, end);
return (*start > tail) ? *start : tail;
}
这是一个常量空间排序算法(这次用C ++),它是O(N!)时间或其左右(可能是O(N * N!)):
void sort(int *start, int *end) {
while (std::next_permutation(start,end));
}
这是一个O(N)空间排序算法,它是O(N ^ 2)时间:
void sort(int *start, int *end) {
std::vector<int> work;
for (int *current = start; current != end; ++current) {
work.insert(
std::upper_bound(work.begin(), work.end(), *current),
*current
);
}
std::copy(work.begin(), work.end(), start);
}
答案 1 :(得分:2)
非常简单的示例:计算字符串中的多个字符。它可以是迭代的:
int length( const char* str )
{
int count = 0;
while( *str != 0 ) {
str++;
count++
}
return count;
}
或递归:
int length( const char* str )
{
if( *str == 0 ) {
return 0;
}
return 1 + length( str + 1 );
}
第一种变体只使用几个局部变量而不管字符串长度 - 它的空间复杂度为O(1)
。第二个如果在没有递归消除的情况下执行,则需要一个单独的堆栈帧来存储对应于每个深度级别的返回地址和局部变量 - 它的空间复杂度为O(n)
,其中n
是字符串长度。
答案 2 :(得分:1)
例如,对数组进行排序算法。您可以使用与放置已排序元素的原始数组长度相同的新数组(Θ( n ))。或者你对数组in-place进行排序,只需使用一个额外的临时变量来交换两个元素(Θ(1))。