我必须打印出字符串中字符出现的次数。我用过类似的东西:
String str="This is sample string";
HashSet<Character> hc= new HashSet<Character>();
for (int i = 0; i < str.length(); i++) {
if(!Character.isSpaceChar(str.charAt(i)) && hc.add( str.charAt(i)) ) {
int countMatches = StringUtils.countMatches(str, str.charAt(i));
System.out.println(str.charAt(i)+" occurs at "+countMatches +" times");
}
}
这是一种解决方案,但是如何分析时间复杂度?我是初学者,所以请引导我完成学习过程。
答案 0 :(得分:3)
首先,如果您想对复杂性分析做一个体面的介绍,那么以下内容看起来不错:
我建议您仔细阅读所有内容,并花时间进行页面中嵌入的练习。
您的代码的复杂性并非微不足道。
从表面上看,循环将执行N次,其中N是输入字符串的长度。但是,如果我们看一下循环的作用,它可以做以下三件事之一:
countMatches
。无所事事的复杂性是O(1)
。
向地图添加条目的复杂度为O(1)
。
调用countMatches
的复杂度为O(N)
,因为它正在查看字符串的每个字符。
现在,如果我们考虑代码的功能,我们可以轻松确定最佳和最差的情况。
当字符串的所有N个字符都是空格时,将出现最佳情况。这给出了O(N)
循环体的O(1)
重复,给出了O(N)
的最佳情况下的复杂性。
最糟糕的情况是所有N个字符都不相同。这使O(N)
循环体的O(N)
重复,给出了O(N^2)
的最坏情况下的复杂度。 (您会认为...但是请继续阅读!)
一般情况如何?如果我们不了解输入字符串的性质,那就很难了。
O(N)
。 最后,即使是最坏的情况也并非真正地 O(N^2)
。字符串是char
值的序列,Java char
的值限制在0到65535之间。因此,在2 ^ 16个不同的字符之后,所有字符都必须重复,因此即使是最坏的情况O(N)
到达无穷大。{p>
(我确实提到这很重要吗?)
答案 1 :(得分:1)
您需要在这里做的是要确定与字符串的长度相关的步骤数的原因。
对于字符串中的每个字符,必须调用一次countMatches
。每次countMatches
的调用都必须再次遍历String的每个字符以对其进行计数。
其他操作(确定字符串的长度,添加到HashSet中,通过索引从字符串中检索字符,检查空格,打印答案)被认为是恒定时间的,并且没有关系。
>某些字符将被跳过的事实(因为它们是空格或已经在HashSet中)不会降低无限制String的复杂性。您可以假设所有字符都不相同的最坏情况。
所以是O(n ^ 2),其中n是字符串的长度。
通过将HashSet更改为计数器的HashMap,可以将其改进为O(n)。然后,您只需要对String进行一次传递,而不是两次嵌套传递。