【发布时间】:2013-02-20 16:11:26
【问题描述】:
我一直在阅读时间复杂度方面的内容,并且已经掌握了基础知识。为了强化这个概念,我看了一下我最近在 SO 上给出的答案。出于某种原因,这个问题现在已经结束,但这不是重点。我不知道我的答案有多复杂,在我得到任何有用的反馈之前问题就被关闭了。
The task 用于查找字符串中的第一个唯一字符。我的回答很简单:
public String firstLonelyChar(String input)
{
while(input.length() > 0)
{
int curLength = input.length();
String first = String.valueOf(input.charAt(0));
input = input.replaceAll(first, "");
if(input.length() == curLength - 1)
return first;
}
return null;
}
我的第一个想法是,因为它会查看每个字符,然后在replaceAll() 期间再次查看每个字符,它会是 O(n^2)。
但是,这让我开始思考它的实际工作方式。对于检查的每个字符,它会删除字符串中该字符的所有实例。所以n 不断缩小。这个因素是如何影响的?那是 O(log n),还是有什么我没看到?
我在问什么:
所写算法的时间复杂度是多少,为什么?
我不是在问什么:
我不是在寻找改进它的建议。我知道可能有更好的方法来做到这一点。我试图更好地理解时间复杂度的概念,而不是找到最佳解决方案。
【问题讨论】:
-
输入字符串的长度,我想。
-
我认为这取决于很多事情:1)
length()是否每次都必须计算字符串中的每个字符,或者是单独存储的长度,因此可以在没有线性扫描的情况下返回? 2) 如果length()是线性的,我们是否至少记住了后续调用的结果? 3) 类使用什么样的内存管理 - 擦除字符是简单的恒定时间操作,还是需要对字符串其余部分进行线性重新复制? 4) 累积擦除何时会导致重新分配和复制?等等…… -
@twalberg:我认为一个安全的假设是
replaceAll必须扫描整个字符串,因为这是“标准”实现,除非另有说明。 -
@recursive Right -
replaceAll当然必须扫描整个字符串以查找匹配项,但问题更多的是实际擦除以及如何处理 - 我可以想到三种同样有效的编写方法replaceAll从我的脑海中浮现出来,但它们在效率上并不相同(将未擦除的字符复制到临时字符串并复制回来,或者在每次擦除时将字符串尾部向左移动,或者以某种方式简单地标记擦除的字符表示“这里没有字符”)... -
@twalberg:鉴于它似乎没有进行就地擦除,(
input = /* ... */) 你的三种方法中的任何一种是否具有其他线性的运行时复杂性?