Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.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_Linked List - Fatal编程技术网

Java 这是从链表中删除重复项的有效方法吗?

Java 这是从链表中删除重复项的有效方法吗?,java,linked-list,Java,Linked List,我正在编写一个函数,它将接收链表的头,删除所有重复项,然后返回新的头。我已经对它进行了测试,但我想看看你是否能发现任何错误或改进它 removeDuplicates(Node head) if(head == null) throw new RuntimeException("Invalid linked list"); Node cur = head.next; while(cur != null) { if(head.data == cur.data

我正在编写一个函数,它将接收链表的头,删除所有重复项,然后返回新的头。我已经对它进行了测试,但我想看看你是否能发现任何错误或改进它

removeDuplicates(Node head)
    if(head == null) throw new RuntimeException("Invalid linked list");

    Node cur = head.next;
    while(cur != null) {
        if(head.data == cur.data) {
            head = head.next;
        } else {
            Node runner = head;
            while(runner.next != cur) {
                if(runner.next.data == cur.data) {
                    runner.next = runner.next.next;
                    break;
                }
                runner = runner.next;
            }
        cur = cur.next;
    } 
    return head;
}

我没有检查你的代码是否有bug,但我有一个改进的建议。分配将节点映射到布尔值的哈希表或哈希映射。在处理每个元素时,如果它不是散列中的键,则添加它(值为Boolean.TRUE)。如果它确实作为一个键存在,那么它已经出现在列表中,您可以简单地删除它

这比您的方法要快,因为哈希查找在大致恒定的时间内工作,而您有一个内部循环,必须为每个列表元素遍历列表的整个剩余部分


此外,您可以考虑是否使用<代码>(或)代码>测试,而不是<代码>=对应用程序有更好的意义。

< P>除了使用列表的元素来创建哈希映射并使用它作为键测试每个元素,这对于大量元素来说是可取的,如果large依赖于创建散列映射所需的资源,则按顺序扫描列表是一个实用的选项,但也有其他方法更快。请参阅user138170的答案-就地合并排序是一个不使用额外空间的O(n log(n))操作,而使用单独分配的数组的解决方案将在O(n)时间内工作。实际上,您可能希望分析代码并确定合理的值n,其中n是列表中的元素数,之后将使用分配内存的解决方案,而不是不使用的解决方案


编辑:如果效率真的很重要,我建议不要使用链表(主要是为了保持缓存一致性),也许可以使用JNI并以本机方式实现该功能;数据还必须在本机分配的缓冲区中提供。

如果您愿意在进程上花费多一点RAM,则可以在不改变结构的情况下使其运行得更快

对于桌面应用程序,我通常倾向于使用更多的内存并赢得一些速度。所以我会这样做

removeDuplicates(Node head) {
    if (head == null) {
        throw new RuntimeException("Invalid List");
    }

    Node current = head;
    Node prev = null;
    Set<T> data = new HashSet<T>(); // where T is the type of your data and assuming it implements the necessary methods to be added to a Set properly.
    while (current != null) {
        if (!data.contains(current.data)) {
            data.add(current.data);
            prev = current;
            current = current.next;
        } else {
            if (prev != null) {
                prev.next = current.next;
                current = current.next;
            }
        }
    }
}
移除的副本(节点头){
if(head==null){
抛出新的运行时异常(“无效列表”);
}
节点电流=头;
Node prev=null;
Set data=new HashSet();//其中T是数据的类型,并假设它实现了正确添加到集合中的必要方法。
while(当前!=null){
如果(!data.contains(current.data)){
data.add(当前数据);
prev=当前值;
当前=当前。下一步;
}否则{
如果(上一个!=null){
prev.next=当前.next;
当前=当前。下一步;
}
}
}
}
这应该在O(n)时间内运行

编辑


我希望我的假设是正确的,即这是一种项目/作业,您被迫使用链表,否则,如前所述,您最好使用不同的数据结构。

要有效地删除重复项,您应该远离链表:改为使用java.util.PriorityQueue;它是一个已排序的集合,您可以为其定义排序条件。如果您总是插入到已排序的集合中,则删除重复项既可以在插入时直接完成,也可以通过一次O(n)传递按需完成。

这是家庭作业吗?或者您不使用
LinkedList
类还有其他原因吗?顺序(嵌套)扫描是O(N*N),而不是O(N!)我的错,我在发布答案后不久就将其编辑掉了。这里的问题不是要有效地修改已经存在的链接列表,不定义正确的数据结构来消除重复?直接插入PriorityQueue会更快,但是如果他不想这样做,原始海报仍然可以使用它来清除O(n)中的链接列表中的重复项。谢谢。我实际上只是在准备技术面试问题。这是一个很好的选择,假设允许您使用额外的数据结构。是的,这是一个很好的面试问题。不太难,你需要一些理论背景。不错!对于少数元素,分配内存所需的时间(取决于分配方案)可能会超过就地修改的合并排序所需的时间。@void pointer-排序将更改链表的结构,我认为不会发生这种情况。