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

发布于 2024-10-20 09:04:53 字数 661 浏览 1 评论 0原文

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

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;
}

I am writing a function that will take in the head of a linked list, remove all duplicates, and return the new head. I've tested it but I want to see if you can catch any bugs or improve on it.

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浴红衣 2024-10-27 09:04:53

如果您愿意在进程上花费更多的 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) 时间内运行。

编辑

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

If you are willing to spend a little more RAM on the process, you can make it go much faster without changing the structure.

For desktop apps, I normally favor using more RAM and winning some speed. So I would do something like this.

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;
            }
        }
    }
}

This should run in O(n) time.

EDIT

I hope I was correct in assuming that this is some kind of project / homework where you are being forced to use a linked list, otherwise, as noted, you would be better off using a different data structure.

素年丶 2024-10-27 09:04:53

我没有检查你的代码是否有错误,但我确实有改进它的建议。分配一个将 Node 映射到 Boolean 的 Hashtable 或 HashMap。当您处理每个元素时,如果它不是哈希中的键,请添加它(使用 Boolean.TRUE 作为值)。如果它确实作为密钥存在,那么它已经出现在列表中,您只需将其删除即可。

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

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

I didn't check your code for bugs, but I do have a suggestion for improving it. Allocate a Hashtable or HashMap that maps Node to Boolean. As you process each element, if it is not a key in the hash, add it (with Boolean.TRUE as the value). If it does exist as a key, then it already appeared in the list and you can simply remove it.

This is faster than your method because hash lookups work in roughly constant time, while you have an inner loop that has to go down the entire remainder of the list for each list element.

Also, you might consider whether using an equals() test instead of == makes better sense for your application.

木森分化 2024-10-27 09:04:53

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

To efficiently remove duplicates you should stay away from linked list: Use java.util.PriorityQueue instead; it is a sorted collection for which you can define the sorting-criteria. If you always insert into a sorted collection removing duplicates can be either done directly upon insertion or on-demand with a single O(n)-pass.

只是一片海 2024-10-27 09:04:53

除了使用列表的元素创建哈希映射并使用它作为键来测试每个元素之外,这仅适用于大量元素,其中取决于所需的资源要创建哈希映射,按顺序扫描列表是一个实用的选择,但还有其他更快的选择。请参阅此处用户138170的答案 - 一个in-地方合并排序是一个O(n log(n))操作,不使用额外的空间,而使用单独分配的数组的解决方案将在O(n)中工作> 时间。实际上,您可能需要分析代码并确定合理的 n 值,,其中 n 是列表中的元素数量,之后分配内存的解决方案将来代替不使用的。

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

Aside from using the elements of the list to create a hash map and testing each element by using it as a key, which would only be desirable for a large number of elements, where large depends on the resources required to create the hash map, sequentially scanning the list is a practical option, but there are others which will be faster. See user138170's answer here - an in-place merge sort is an O(n log(n)) operation which does not use an extra space, whereas a solution using separately-allocated array would work in O(n) time. Practically, you may want to profile the code and settle for a reasonable value of n, where n is the number of elements in the list, after which a solution allocating memory will be used instead of one which does not.

Edit: If efficiency is really important, I would suggest not using a linked list (largely to preserve cache-coherency) and perhaps using JNI and implementing the function natively; the data would also have to be supplied in a natively-allocated buffer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文