java是编写这个程序的最佳方式
我有一个一般的编程问题,我碰巧用Java来回答。问题是:
给定一个整数数组,编写一个程序,找出数组中有多少个非唯一的数字。(例如,{2,3,2,5,6,1,3}2中的数字(2和3)不是唯一的)。你的程序执行多少操作(以O表示法)
这是我的解决方案
int counter = 0;
for(int i=0;i<theArray.length-1;i++){
for(int j=i+1;j<theArray.length;j++){
if(theArray[i]==theArray[j]){
counter++;
break; //go to next i since we know it isn't unique we dont need to keep comparing it.
}
}
}
return counter:
现在,在我的代码中,每个元素都会与其他元素进行比较,所以大约有n(n-1)/2个操作。给出O(n^2)。如果您认为我的代码不正确/效率低下,或者我的O表达式错误,请告诉我
# 1 楼答案
你的分析是正确的,但你可以很容易地把它归结为O(n)时间。在遍历数组时,尝试使用
HashMap<Integer,Integer>
存储以前看到的值(key是您看到的数字,value是您看到它的次数)。每次尝试向hashmap中添加一个整数时,请检查它是否已经存在。如果是,只需增加整数计数器。然后,在最后,在地图中循环,并计算您看到相应值大于1的键的次数# 2 楼答案
正如其他人所说,O(n)解决方案很可能使用散列。在Perl中:
输出
# 3 楼答案
我认为你的
O(n^2)
时间复杂度是正确的如果空间复杂度不是问题,那么可以使用256个字符(ASCII)的标准数组,并开始用值填充它。例如 //可能需要将所有值初始化为0。我不知道。但是下面可以用
O(n+m)
完成,其中n是数组的长度,m是数组的长度# 4 楼答案
你的代码不符合你的要求。如果使用数组
{2, 2, 2, 2}
运行它,会发现它返回2而不是1。你必须找到一种方法来确保计数不再重复然而,作为最坏情况分析,你的大O表达式是正确的,因为每个元素都可能与其他元素进行比较
# 5 楼答案
为什么不像下面的例子那样使用
Map
注意,这个方法需要迭代列表两次(我相信有一种方法可以迭代一次)。它在
theArray
中迭代一次,然后在迭代elementCount
的键集时隐式地再次迭代,如果没有两个元素是相同的,那么键集将完全一样大。然而,连续两次遍历同一个列表仍然是O(n)而不是O(n^2),因此具有更好的渐近运行时间# 6 楼答案
首先,你的方法就是我所说的“蛮力”,在最坏的情况下,它确实是O(n^2)。它的实现也不正确,因为重复n次的数字被计数n-1次
撇开这一点不谈,有很多方法可以解决这个问题。第一个(许多答案都建议)是迭代数组,并使用一个映射来跟踪给定元素被看到的次数。假设映射使用哈希表作为底层存储,平均大小写复杂度应该是O(n),因为来自映射的get和insert平均应该是O(1),并且您只需要对列表和映射进行一次迭代。请注意,在最坏的情况下,这仍然是O(n^2),因为不能保证哈希将产生连续时间结果
另一种方法是先对数组进行排序,然后迭代排序后的数组以查找重复项。这种方法完全取决于所选的排序方法,可以是O(n^2)(对于简单冒泡排序)到O(n logn)最坏情况(对于合并排序)到O(n logn)平均情况(尽管可能是快速排序)
这是假设数组中存在任意对象的排序方法所能做的最好的事情。不过,因为您的示例涉及整数,所以使用基数排序可以做得更好,它的最坏情况复杂性为O(dn),其中d基本上是常量(因为32位整数的最大值为9)
最后,如果您知道元素是整数,并且它们的大小不太大,那么可以通过使用size ElementMax数组来改进基于映射的解决方案,这将保证O(n)最坏情况的复杂性,同时需要额外的4*ElementMax字节内存