确定数字是否仅在数组中出现一次

时间:2013-05-15 15:52:08

标签: java algorithm big-o puzzle

这是一个家庭作业问题,我已经考虑了很长一段时间了,并提出了几个解决方案,但我认为存在更好的解决方案。

确定阵列中是否存在仅出现一次的元素(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)时间。

3 个答案:

答案 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