Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中有效地从大量数组中删除重复字符串?_Java - Fatal编程技术网

在java中有效地从大量数组中删除重复字符串?

在java中有效地从大量数组中删除重复字符串?,java,Java,我正在考虑从一个(未排序的)字符串数组中删除重复项的最佳方法-该数组包含数百万或数千万个stringz..该数组已预填充,因此优化目标只是删除DUP,而不是阻止DUP最初填充 我想先进行排序,然后进行二进制搜索,得到一个日志(n)搜索,而不是n(线性)搜索。这将给我nlogn+n搜索,虽然比未排序的(n^2)搜索要好,但这看起来仍然很慢。(也在考虑散列,但不确定吞吐量) 请帮忙!正在寻找一种既能解决速度问题又能解决内存问题的高效解决方案,因为在不使用Collections API的情况下涉及数百

我正在考虑从一个(未排序的)字符串数组中删除重复项的最佳方法-该数组包含数百万或数千万个stringz..该数组已预填充,因此优化目标只是删除DUP,而不是阻止DUP最初填充

我想先进行排序,然后进行二进制搜索,得到一个日志(n)搜索,而不是n(线性)搜索。这将给我nlogn+n搜索,虽然比未排序的(n^2)搜索要好,但这看起来仍然很慢。(也在考虑散列,但不确定吞吐量)


请帮忙!正在寻找一种既能解决速度问题又能解决内存问题的高效解决方案,因为在不使用Collections API的情况下涉及数百万字符串

直到你的最后一句话,答案对我来说似乎是显而易见的:如果你需要保持秩序,请使用
HashSet
LinkedHashSet

HashSet<String> distinctStrings = new HashSet<String>(Arrays.asList(array));
HashSet distinctStrings=新的HashSet(Arrays.asList(array));

如果不能使用集合API,请考虑建立自己的哈希集…但是,在给出不想使用collections API的原因之前,很难给出更具体的答案,因为这个原因可能会排除其他答案。

您好,您需要将它们放入数组中吗。使用散列值(如集合)来使用集合会更快。这里每个值都是唯一的,因为它的散列值是唯一的

如果将所有条目放入集合类型。你可以使用

 HashSet(int initialCapacity) 
构造函数来防止运行时内存扩展

  Set<T> mySet = new HashSet<T>(Arrays.asList(someArray))
Set mySet=newhashset(Arrays.asList(someArray))

如果不需要扩展内存,Arrays.asList()的运行时为O(n)。

我建议您在数组上使用修改后的mergesort。在合并步骤中,添加逻辑以删除重复值。此解决方案的复杂性为n*log(n),如果需要,可以就地执行(在这种情况下,就地执行比使用普通mergesort要困难一些,因为相邻部分可能包含删除的重复项的间隙,在合并时也需要关闭这些间隙)


有关mergesort的更多信息,请参见

,因为这是一个面试问题,我认为他们希望您提出自己的实现,而不是使用set api

您可以构建一个二叉树并创建一个空数组来存储结果,而不是先对其进行排序然后再进行比较

数组中的第一个元素将是根

  • 如果下一个元素等于节点,则返回。->这将删除重复的元素

  • 如果下一个元素小于节点,请将其与左侧进行比较,否则将其与右侧进行比较

  • 继续执行上述两个步骤,直到到达树的末尾,然后您可以创建一个新节点,并且知道它还没有重复。 将此新节点值插入数组

    遍历原始数组的所有元素后,您将获得一个数组的新副本,并且在原始顺序中没有重复项


    遍历需要O(n),搜索二叉树需要O(logn)(插入只需要O(1),因为您只是附加它,而不是重新分配/平衡树),因此总数应该是O(nlogn)。

    分析

    让我们进行一些分析:

  • 使用HashSet。时间复杂度-O(n)。空间复杂度O(n)。请注意,它需要大约8*个数组大小字节(8-16字节-对新对象的引用)

  • 快速排序。时间-O(n*logn)。空间O(logn)(分别为最坏情况O(n*n)和O(n))

  • 合并排序(二叉树/树集)。时间-O(n*logn)。空间O(n)

  • 堆排序。时间O(n*logn)。空间O(1)。(但它比2和3慢)

  • 在堆排序的情况下,您可以动态地清除重复项,以便在排序后保存最后一次

    结论

  • 如果您关心时间,并且不介意为哈希集分配8*array.length字节,那么这个解决方案似乎是最佳的

  • 如果空间是一个问题-那么快速排序+一次通过

  • 如果空间是一个大问题,那么实现一个堆,并动态地丢弃重复项。它仍然是O(n*logn),但没有额外的空间


  • 创建一个hashset来处理这个任务太昂贵了。很明显,事实上,他们告诉您不要使用Collections API的全部目的是因为他们不想听到hash这个词。这就剩下下面的代码了

    请注意,在对数组排序后,您向他们提供了二进制搜索:这毫无意义,这可能是您的建议被拒绝的原因

    备选案文1:

    public static void removeDuplicates(String[] input){
        Arrays.sort(input);//Use mergesort/quicksort here: n log n
        for(int i=1; i<input.length; i++){
            if(input[i-1] == input[i])
                input[i-1]=null;
        }       
    }
    
    publicstaticvoidremoveduplices(字符串[]输入){
    Arrays.sort(输入);//在此处使用mergesort/quicksort:n log n
    
    对于(inti=1;iO.K.,如果他们想要超高速,让我们尽可能多地使用字符串的哈希码

  • 循环遍历数组,获取每个字符串的哈希代码,并将其添加到您喜爱的数据结构中。由于不允许使用集合,请使用位集。请注意,您需要两个位集,一个为正数,一个为负数,它们都将是巨大的

  • 使用另一个位集在数组中再次循环。True表示字符串通过。如果该位集中不存在该字符串的哈希代码,则可以将其标记为True。否则,将其标记为可能重复,或标记为false。在进行此操作时,计算可能重复的数量

  • 将所有可能的重复项收集到一个名为possibleDuplicates的大字符串[]中。对其进行排序

  • 现在检查原始数组中可能存在的重复项,并在可能的重复项中进行二进制搜索。如果存在,那么,您仍然被卡住了,因为您希望只包含一次,而不是所有其他时间。因此,您需要另一个数组。混乱,我必须
    public static String[] removeDuplicates(String[] input){
        Arrays.sort(input);//Use mergesort here: n log n
        int size = 1;
        for(int i=1; i<input.length; i++){
            if(input[i-1] != input[i])
                size++;
        }
        System.out.println(size);
        String output[] = new String[size];
        output[0]=input[0];
        int n=1;
        for(int i=1;i<input.length;i++)
            if(input[i-1]!=input[i])
                output[n++]=input[i];
        //final step: either return output or copy output into input; 
        //here I just return output
        return output;
    }
    
    public static String[] removeDuplicates(String[] input){
        Arrays.sort(input);//Use mergesort/quicksort here: n log n
        int outputLength = 0;
        for(int i=1; i<input.length; i++){
            // I think equals is safer, but are nulls allowed in the input???
            if(input[i-1].equals(input[i]))
                input[i-1]=null;
            else
               outputLength++;
        }  
    
        // check if there were zero duplicates
        if (outputLength == input.length)
           return input;
    
        String[] output = new String[outputLength];
        int idx = 0;
        for ( int i=1; i<input.length; i++) 
           if (input[i] != null)
              output[idx++] = input[i]; 
    
        return output;   
    }