繁体   English   中英

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

[英]Is this an efficient way to remove duplicates from a 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) {
            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;
}

如果您愿意在该过程上花费更多的RAM,则可以在不更改结构的情况下使其运行更快。

对于台式机应用程序,我通常倾向于使用更多的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;
            }
        }
    }
}

这应该在O(n)时间内运行。

编辑

我希望我认为这是某种项目/作业,在这种情况下您被迫使用链表是正确的,否则,如上所述,最好使用其他数据结构。

我没有检查您的代码中的错误,但确实有改进建议。 分配将Node映射为布尔值的Hashtable或HashMap。 在处理每个元素时,如果它不是哈希中的键,则添加它(使用Boolean.TRUE作为值)。 如果它确实作为键存在,则它已经出现在列表中,您可以简单地将其删除。

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

另外,您可能会考虑使用equals()测试代替==是否对您的应用程序更有意义。

为了有效地删除重复项,您应该远离链表:使用java.util.PriorityQueue代替; 它是一个已排序的集合,您可以为其定义排序标准。 如果您始终插入已排序的集合中,则删除可以直接在插入时进行,也可以按一次O(n)传递按需进行。

除了使用列表中的元素来创建哈希图并通过将其用作键来测试每个元素外,这仅对大量元素有用,在很大程度上依赖于创建哈希图所需的资源扫描列表是一个实际的选择,但是还有其他选择会更快。 在此处查看user138170的答案-就地合并排序是O(n log(n))操作,它不使用多余的空间,而使用单独分配的数组的解决方案将在O(n)的时间内工作。 实际上,您可能需要分析代码并确定n的合理值其中n是列表中元素的数量,此后将使用分配内存的解决方案而不是不分配内存的解决方案。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM