这是一个家庭作业问题,我已经考虑了很长一段时间了,并提出了几个解决方案,但我认为存在更好的解决方案。
确定阵列中是否存在仅出现一次的元素(int)的最快方法是什么?任何元素都可以出现任意次。 {3,1,4,1,4,3}将返回false,而{3,1,4,1,4,1}将返回true(3出现一次)。
我们只允许使用我们已经学过的东西(所有基础知识,递归,oop,搜索和排序算法,包括快速排序),因此制作哈希表不是一种选择。
到目前为止,我提出的最佳实用解决方案是使用quicksort对其进行排序然后通过它(O(nlogn)),我提出的最好的不切实际的解决方案是创建一个大的数组,其大小与所有可能的int值和然后使用它的地方类似于哈希表(但该数组太大而无法实际实现)(O(n))
在O(n)时间内有另一种(实用的)方法吗?
编辑:刚收到TA的回答,我听说的建议的O(n)解决方案是不实用的(与我建议的相同或相似),因此他们告诉我们不要使用它。我99%肯定现在最好的实际答案(没有哈希表)是O(nlogn)时间。答案 0 :(得分:5)
您可以使用自定义的快速排序来查找不同的值,而不会在之后迭代排序的数组。
当您选择了一个数据透视值并且正在移动数组的相应部分时,如果该值与数据透镜匹配,则丢弃它并在移动数组部分后丢弃透视值,这将删除重复项在数组最终排序之前。
即:
Sorting [5, 1, 4, 1, 4, 1]
If you choose the pivot as 4, you'd end up with the 2 sub arrays being:
[1, 1, 1] and [5]
如果永远不会丢弃您的数据透视表,那么它是不同的,如果它被丢弃,则在子列表上执行相同的处理。如果子列表只有1个元素,则它是不同的。
通过这种方式,您可以更早地获取不同的值。
编辑:是的,这仍然受到O(nlogn)的约束(我认为?)
答案 1 :(得分:0)
您基本上必须进行冒泡排序样式比较。没有内置函数来回答问题,即使你排序,你仍然必须迭代每个元素(甚至只是为了找到组中断时)。你可以用多个数组做一些更复杂的方法,特别是如果你需要找到哪些元素只返回一次。
但是一旦你找到一个出现一次,你可以打破。这段代码可以做到。它是O(n ^ 2),但我不确定你能为这个问题做得更快。
boolean anySingles(int[] data])
{
outer:
for (int i = 0; i < data.length - 1; i++)
{
for (int j = 0; i < data.length; j++)
{
if (i != j)
{
if (data[i] == data[j]) continue outer;
}
}
// made it to the end without finding a duplicate
return true;
}
return false;
}
答案 2 :(得分:0)
让我们做一个实验:
package test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
/**
* Created with IntelliJ IDEA.
* User: Nicholas
* Date: 15.05.13
* Time: 21:16
*/
public class Searcher {
private static boolean searchBySorting(int [] array){
int [] newArray = new int[array.length];
System.arraycopy(array, 0, newArray,0, array.length);
Arrays.sort(newArray);
for (int i = 0; i < newArray.length - 2; ++i){
if(newArray[i] == newArray[i + 1]){
return true;
}
}
return false;
}
private static boolean searchByCompare(int [] array){
int [] newArray = new int[array.length];
System.arraycopy(array, 0, newArray,0, array.length);
for (int i = 0; i < newArray.length - 1; ++i){
int value = newArray[i];
for(int j = i + 1; j < newArray.length - 1; ++j){
if(value == newArray[j]){
return true;
}
}
}
return false;
}
private static boolean searchBySet(int [] array){
int [] newArray = new int[array.length];
System.arraycopy(array, 0, newArray,0, array.length);
Set<Integer> set = new HashSet<Integer>();
for (int i = 0; i < newArray.length; ++i){
if(set.contains(newArray[i])){
return true;
}
set.add(newArray[i]);
}
return false;
}
private static int [] generateRandomArray(){
Random random = new Random();
int size = random.nextInt(1000) + 100;
int [] array = new int[size];
for (int i = 0; i < size; ++i){
array[i] = random.nextInt();
}
return array;
}
public static void main(String [] args){
long sortingTime = 0;
long compareTime = 0;
long setTime = 0;
for (int i = 0; i < 1000; ++i){
int [] array = generateRandomArray();
long begin = System.currentTimeMillis();
for(int j = 0; j < 100; ++j){
searchBySorting(array);
}
long end = System.currentTimeMillis();
sortingTime += (end - begin);
begin = System.currentTimeMillis();
for(int j = 0; j < 100; ++j){
searchByCompare(array);
}
end = System.currentTimeMillis();
compareTime += (end - begin);
begin = System.currentTimeMillis();
for(int j = 0; j < 100; ++j){
searchBySet(array);
}
end = System.currentTimeMillis();
setTime += (end - begin);
}
System.out.println("Search by sorting: " + sortingTime + " ms");
System.out.println("Search by compare: " + compareTime + " ms");
System.out.println("Search by insert: " + setTime + " ms");
}
}
我的结果:
按排序搜索:2136毫秒
按比较搜索:11955 ms
按插入搜索:4151 ms
有任何问题吗?
PS。我所知道的最佳算法是Tortoise and hare