该代码执行的时间复杂度是多少?

时间:2019-10-12 12:51:41

标签: java time-complexity

我必须打印出字符串中字符出现的次数。我用过类似的东西:

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");
    }
}

这是一种解决方案,但是如何分析时间复杂度?我是初学者,所以请引导我完成学习过程。

2 个答案:

答案 0 :(得分:3)

首先,如果您想对复杂性分析做一个体面的介绍,那么以下内容看起来不错:

我建议您仔细阅读所有内容,并花时间进行页面中嵌入的练习。


您的代码的复杂性并非微不足道。

从表面上看,循环将执行N次,其中N是输入字符串的长度。但是,如果我们看一下循环的作用,它可以做以下三件事之一:

  1. 如果角色是空格,则不会执行其他任何操作
  2. 如果字符不是空格,则将其添加(或重新添加)到哈希图中
  3. 如果添加了字符,则会调用countMatches

无所事事的复杂性是O(1)

向地图添加条目的复杂度为O(1)

调用countMatches的复杂度为O(N),因为它正在查看字符串的每个字符。

现在,如果我们考虑代码的功能,我们可以轻松确定最佳和最差的情况。

  • 当字符串的所有N个字符都是空格时,将出现最佳情况。这给出了O(N)循环体的O(1)重复,给出了O(N)的最佳情况下的复杂性。

  • 最糟糕的情况是所有N个字符都不相同。这使O(N)循环体的O(N)重复,给出了O(N^2)的最坏情况下的复杂度。 (您会认为...但是请继续阅读!)

一般情况如何?如果我们不了解输入字符串的性质,那就很难了。

  • 如果随机选择字符,则重复字符的可能性较小,而空格字符的可能性较小。
  • 如果字符是字母文本,则空格更频繁,重复也更频繁。确实,对于英语文本字符,很可能仅限于大写和小写拉丁字母(52)以及少数标点符号。因此,对于长字符串和性能,您可能期望大约60个映射条目,这些性能会迅速收敛到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进行一次传递,而不是两次嵌套传递。