这些“for”循环的更有效替代方案?

时间:2015-10-19 21:32:16

标签: java

我正在学习Java的入门课程,我最近的一个项目涉及确保数组不包含任何重复元素(具有不同的元素)。我使用带有内部for循环的for循环,它可以工作,但我听说你应该尽量避免在程序中使用很多迭代(我的类中的其他方法也有相当多的迭代次数)。这个代码有没有有效的替代方案?我当然不是要求代码,只是“概念”。是否有可能以递归方式执行此操作?谢谢!

数组大小通常<= 10。

/** Iterates through a String array ARRAY to see if each element in ARRAY is
 *  distinct. Returns false if ARRAY contains duplicates. */
boolean distinctElements(String[] array) { //Efficient?
    for (int i = 0; i < array.length; i += 1) {
        for (int j = i + 1; j < array.length; j += 1) {
            if (array[i] == array[j]) {
                return false;
            }
        }
    } return true;
}

2 个答案:

答案 0 :(得分:1)

首先,array[i] == array[j]测试引用相等性。这不是你如何测试String(s)的价值平等。 我会将每个元素添加到Set。如果未成功添加任何元素(因为它是重复的),Set.add(E)将返回false。像,

static boolean distinctElements(String[] array) {
    Set<String> set = new HashSet<>();
    for (String str : array) {
        if (!set.add(str)) {
            return false;
        }
    }
    return true;
}

您可以在没有像

这样的短路的情况下渲染上述内容
static boolean distinctElements(String[] array) {
    Set<String> set = new HashSet<>(Arrays.asList(array));
    return set.size() == array.length;
}

答案 1 :(得分:1)

&#34;效率&#34;几乎总是一个权衡。偶尔,有些算法比其他算法更好,但通常它们在某些情况下只会更好。

例如,上面的代码:它的时间复杂度O(n^2)

一种改进可能是对字符串进行排序:然后,您可以通过比较元素是否等于其邻居来比较字符串。由于排序,这里的时间复杂度降低到O(n log n),这主导了元素的线性比较。

然而 - 如果您不想更改数组的元素会怎么样 - 例如,您的代码的其他一些部分依赖于它们的原始顺序 - 现在您还必须复制数组然后对它进行排序,然后查找重复项。这不会增加总体时间或存储复杂性,但它会增加整体时间存储,因为正在完成更多工作并需要更多内存。

Big-oh表示法只会限制忽略乘法因子的时间。也许你只能访问一个非常慢的排序算法:实际上,只使用你的O(n^2)循环会更快,因为那样你就不必调用非常慢的排序。

当您输入非常小时可能就是这种情况。经常被引用的一个算法,它具有较差的时间复杂度但实际上在实践中很有用的是冒号排序:在最坏的情况下它是O(n^2),但是如果你有一个小的和/或接近排序的数组,它实际上可以非常快速,而且实现起来非常简单 - 永远不要忘记你必须编写和调试代码的低效率,并且当它没有像你期望的那样工作时必须提出问题

如果您知道元素已经排序,那该怎么办?因为您对其来源有所了解。现在,您可以简单地遍历数组,比较邻居,现在时间复杂度为O(n)。我不记得我在哪里读过它,但我曾经看到一篇博文说(我解释):

  

永远不能使给定的计算机更快;它只会做更少的工作。

如果您可以利用某些财产来减少工作量,那么可以提高效率。

因此,效率是一个主观标准:

  • 每当你提出这个问题时,你必须能够回答这个问题:&#34; 的效率如何?&#34;。它可能是空间;可能是时间;可能需要多长时间才能编写代码。
  • 您必须知道您将要运行的硬件限制 - 内存,磁盘,网络要求等可能会影响您的选择。
  • 您需要了解代表您运行它的用户的要求。一个用户可能希望尽快得到结果;另一个用户明天可能想要结果。从来没有必要找到比#34更好的解决方案&#34; (尽管一旦用户看到可能的情况,这可能是一个移动目标。)
  • 您还必须知道您希望它对哪些输入有效,以及您可以利用哪些属性来避免不必要的工作。