【问题标题】:Optimize code with ArrayList or TreeSet?使用 ArrayList 或 TreeSet 优化代码?
【发布时间】:2014-04-13 06:41:01
【问题描述】:
TreeMap<String,ArrayList<String>> statesToPresidents = new TreeMap<String,ArrayList<String>>();
    TreeMap<String,String> reversedMap = new TreeMap<String,String>();
    TreeSet<String> presidentsWithoutStates = new TreeSet<String>();
    TreeSet<String>statesWithoutPresidents = new TreeSet<String>(); while (infile2.ready())
    {
        String president = infile2.readLine();
        if (reversedMap.containsKey(president)==false)
            presidentsWithoutStates.add(president);
    }

    infile2.close();

    System.out.println( "\nThese presidents were born before the states were formed:\n");  // DO NOT REMOVE OR MODIFY

    // YOUR CODE HERE TO PRINT THE NAME(S) Of ANY PRESIDENT(s)
    //  WHO WERE BORN BEFORE THE STATES WERE FORMED = 10%

    Iterator<String> iterator = presidentsWithoutStates.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }

我想知道如果我使用 ArrayList 而不是 TreeSet,我的程序是否会运行得更快。如果它不是 reversedMap 中的键并且当我打印出来时我需要它的排序顺序,我将字符串总裁添加到总裁WithoutStates TreeSet。我应该使用 TreeSet 并随时排序,还是应该只使用 arraylist 并在最后进行排序。我看到了一个类似的问题,但那个人并没有像我一样不断添加元素。

编辑:没有重复

【问题讨论】:

  • 在我看来,您似乎在利用 TreeSet 的排序和键查找的优势来证明增加的开销是合理的。如果你只使用排序,你还不如只使用 ArrayList,如果你只使用键查找,你应该使用 HashMap。只是我的看法,可能还有其他人不同意。

标签: java optimization data-structures arraylist treeset


【解决方案1】:

让我们分解运行时间:

数组列表:

  • n 插入以摊销的O(1) 每个,给我们O(n)

  • 排序采用O(n log n),假设您使用内置的Collections.sort,或O(n log n) 排序算法。

  • 遍历它需要O(n)

总计 = O(n + n log n) = O(n log n)

树集:

  • n 插入每个O(log n),给我们O(n log n)

  • 遍历它需要O(n)

总计 = O(n log n + n) = O(n log n)

结论:

渐近地,我们有相同的表现。

实际上,ArrayList 可能会稍微快一些。

我为什么这么说?好吧,让我们假设它不是。然后我们可以使用TreeSet 对数组进行排序,比专门对其进行排序的方法更快(不必插入ArrayList 所节省的成本相当小)。这似乎违反直觉,不是吗?如果这(始终)是真的,Java 开发人员会简单地用 TreeSet 替换该方法,不是吗?

可以分析与排序相关的常数因子与TreeSet,但这可能相当复杂,并且程序运行的条件也会影响常数因子,因此不能准确。

关于重复的注意事项:

以上假设没有任何重复。

如果有重复项,您绝对不应该使用contains 检查是否要使用ArrayList,而是在之后进行重复删除(这可以通过简单地忽略连续元素来完成,这些元素是排序后的迭代过程中相同)。应该避免contains 检查的原因是因为它需要O(n),这可能会使整个事情改为O(n²)

如果有很多重复,TreeSet 可能会更快,因为它只需要O(n log m),其中m 是重复的数量。排序选项不会如此直接地处理重复项,因此,除非m 非常小,或者你很幸运,否则最终仍会选择O(n log n)

TreeSet 变得比排序选项更快的确切点确实需要进行基准测试。

【讨论】:

  • 您是否考虑在插入之前检查重复项?对我来说,ArrayList 的插入似乎是 O(n^2)
  • @dcharms 如果您插入重复项并在之后迭代时忽略它们,您仍然会得到一个 O(n log n) 算法。对此添加了注释。
  • 这是有道理的,我没有这样想过。感谢您的补充说明。
猜你喜欢
  • 1970-01-01
  • 2018-01-10
  • 2014-05-24
  • 1970-01-01
  • 2022-11-23
相关资源
最近更新 更多