此方法如何在Big O表示法中执行?

时间:2013-12-04 10:21:42

标签: java list map big-o

下面的方法“getValue”解析一个String,根据String构建一个Map并返回一个与该键相关联的值。 以下方法的性能是“getValue”O(n)的平方吗?

我基于此,因为每次添加新的键值字符串时,都需要对其进行解析,然后将该项添加到Map中。

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class MeasureBigO {

    private static final String testString = "keyTest=keyValue";

    public static void main(String args[]){

        System.out.println(getValue("keyTest"));

    }

    private static String getValue(String key){

        Map<String, String> config = new java.util.HashMap<String, String>();
        List<String> configItems = Arrays.asList(testString.split(","));

        for (String configItem : configItems) {
            configItem = configItem.trim();
            List<String> keyValuesPairs = Arrays.asList(configItem.split("="));

            try {
                config.put(keyValuesPairs.get(0).trim(), keyValuesPairs.get(1).trim());
            }
            catch(IndexOutOfBoundsException ioobe){
                return null;
            }
        }

        return config.get(key);

    }

}

2 个答案:

答案 0 :(得分:5)

此算法的复杂性为O(n),其中nconfigItems中的项目数。

  • 我的格式为testString:可以在O(1)时间内拆分。
  • 围绕configItems的循环与O(n)成比例。
  • split的其他configItem操作也是O(1)

除了他们之外,你的循环中还有说明,所以在实践中它是C * O(n),其中C是一些不变的成本。

答案 1 :(得分:2)

将字符串拆分为列表项将相对于字符串的大小为O(n)。

将这些项目拆分成对将是O(n * m),相对于对的数量(n,它与先前的源字符串的长度有关)和每个字符串的大小(m)。在实践中,我们可以假设每个字符串的大小与对的数量相比可以忽略不计。

相对于对的数量,将这些添加到散列映射将是O(n)。 假设高于正常的哈希冲突没有问题,检索该值大约为O(1)。

由于这里的所有n都与同一事物有关,我们有O(n)+ O(n * m)+ O(n)+ O(1)。当我们在计算复杂度的顺序时忽略低阶,这将是O(n * m)。但是,如上所述,我们希望m扫描能够找到可忽略不计的关键,特别是下面提到的修复,所以我们只说O(n)。

另一种看待这种情况的方法是第一次操作需要c₀ * n + k₀,其中c 0是每个项目完成的恒定工作量,而k 0是整个操作的恒定工作量。接下来需要c₁ * n * m + k₁,下一个c₂ * n + k₂和最终查找c₃ * 1。添加k₄作为方法本身的常量开销,我们有:

c₀ * n + k₀ + c₁ * n * m + k₁ + c₂ * n + k₂ + c₃ * 1 + k₄

等于:

(c₁ * n * m) + (c₀ + c₂) * n + c₃ + k₀ + k₁ + k₂ + k₄

如果我们可以忽略n * m,那么删除较低的订单会给我们一个与nm成比例的时间。因此,O(n * m)或O(n)取决于我们是否可以忽略每个键值对的大小。

这里值得注意的两件事。第一个是将configItem.split("=")的调用替换为configItem.split("=", 2),这样可以提高正确性(捕获值包含=的情况),并使m与大小成比例关键而不是整对,让我们更有信心假设它可以忽略不计(事实上,在提供轻微的性能提升方面)。

第二个是假设键值对的源集没有改变,那么我们可以在设置时创建哈希映射,或者在第一次调用方法时创建哈希映射,然后再次使用它后续电话。然后,这将使方法O(1)具有初始O(n)设置。

相反,如果源集确实发生了变化,那么根本就没有必要使用地图,只要在迭代对中找到匹配的密钥就可以立即返回值;因此采用O(n)方法,但常数较小,平均只检查成对匹配的一半。