我正在学习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;
}
答案 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)
。我不记得我在哪里读过它,但我曾经看到一篇博文说(我解释):
永远不能使给定的计算机更快;它只会做更少的工作。
如果您可以利用某些财产来减少工作量,那么可以提高效率。
因此,效率是一个主观标准: