【发布时间】:2017-05-29 23:42:43
【问题描述】:
给定一个整数
p和目标基b,返回基b中p的字符串表示。字符串的末尾应该有最低有效位
^ 这是我给自己的问题。
我想出的朴素递归算法(C++)如下:
string convertIntToBaseRecursive(int number, int base) {
// Base case
if (!number) return "";
// Adding least significant digit to "the rest" computed recursively
// Could reverse these operations if we wanted the string backwards.
return convertToBaseRecursive(number / base, base) + to_string(number % base);
}
虽然算法非常简单,但我想确保自己了解复杂性细分。我的想法在下面,我想知道它们是正确的还是错误的,如果它们是错误的,那么知道我在哪里偏离轨道会很好!
声明:
-
n = logb(p)是返回字符串的长度 - 时间复杂度:
O(n^2) - 空间复杂度:
O(n)
推理:
为了在字符串末尾保留最低有效位,当它是我们在其他任何东西之前计算的值时,我们要么必须:
- 按原样递归计算字符串
- 每次我们计算一个位时都保持“移动”数组,这样我们就可以将最近的位添加到字符串的前面,而不是结尾
- 将字符串倒写,并在返回之前将其反转(最有效)
我们正在执行上述 C++ 算法中的第一种方法,+ 运算符在每个堆栈帧处创建一个新字符串。初始帧创建并返回一个长度为n 的字符串,下一帧创建一个长度为n-1、n-2、n-3 等的字符串。遵循这一趋势(无需证明为什么1 + 2 + 3 ... + n = O(n^2),很明显时间复杂度是O(n^2) = O(logb^2(p))。我们也只需要随时将O(n) 的东西存储在内存中。当原始堆栈帧解析(就在算法完成之前)我们将拥有原始字符串的内存,但在它解析之前它将是单个字符(O(1))+递归堆栈帧(O(n))。我们这样做this 在每个级别存储n 数量的单个字符,直到我们完成。因此空间复杂度为O(n)。
当然,这个解决方案更有效的版本是
string convertIntToBaseIterative(int number, int base) {
string retString = "";
while (number) {
retString += to_string(number % base);
number /= base;
}
// Only needed if least significant
reverse(retString.begin(), retString.end());
return retString;
}
我相信上面的解决方案,n = logb(p) 有:
- 时间复杂度:
O(n) - 空间复杂度:
O(n)
这些分析是正确的还是我不在某个地方?
【问题讨论】:
标签: c++ algorithm recursion numbers base