【问题标题】:Remove duplicates from an unsorted linked list, Cracking the coding interview从未排序的链表中删除重复项,破解编码面试
【发布时间】:2016-03-07 11:57:14
【问题描述】:

我正在通读 Cracking the coding interview by Gayle Mcdowell 这本书,并遇到了针对第 2 节链接列表中的一个问题的替代解决方案。特别是问题#2.1

删除重复项:编写代码以从未排序的链表中删除重复项。如果不允许使用临时缓冲区,您将如何解决此问题。

Example input  = [1,2,2,6,4,4,2] 

Example output = [1,2,6,4]

作者在书中给出的答案如下: 基本上,它保持“指针”,一个遍历链表,另一个检查所有后续节点是否有重复:

    public void deleteDups(Node head) {
    Node current = head;
    while (current != null) {
        Node runner = current;
        while (runner.next != null) {
            if (runner.next.data == current.data) {
                runner.next = runner.next.next;
            } else {
                runner = runner.next;
            }
        }
        current = current.next;
    }
}

我使用了递归,我的代码看起来有点不同,尽管(我相信)做同样的事情:

public void removeRepetites(Node head) {
    if (head == null) return;
    int dataToRemove = head.data;
    while (head.next != null) {
        if (head.next.data == dataToRemove) {
            head.next = head.next.next;
        } else {
            removeRepetites(head.next);
            head = head.next;
        }
    }
}

你能发现我解决问题的方式有什么缺点吗?也许是更高的 O 空间/时间复杂度?

谢谢!

【问题讨论】:

    标签: java data-structures linked-list


    【解决方案1】:

    您的代码将如何处理包含 1,000,000 个唯一项目的列表?

    假设没有编译器或运行时优化,您的代码会stackoverflow。

    这就是为什么尾递归更好地优化为循环的原因。如果你这样做了,我想,它看起来就像书中的答案。

    【讨论】:

    • 谢谢!事实上,正如我们所说,我正在我的代码中执行基准测试。会告诉你进展如何
    • 你是对的,我的资源更密集,完成同样的任务需要相当长的时间。实际上,运行一个有 50 个节点的链表大约需要 5 秒。虽然作者的回答只需要 2 毫秒
    【解决方案2】:

    就复杂性而言,在我看来,这两种实现都将导致 O(n^2) 复杂性,因为迭代答案涉及嵌套循环,而您的则涉及在 a 内递归调用 n 次的函数循环执行 n 次。

    我发现你的唯一问题/缺点是,由于它是递归的,由于对函数的递归调用,它会更快地填充堆栈空间。每次调用该函数时,它都会在堆栈中创建一个指向该函数的指针以及 dataToRemove 变量。

    【讨论】:

      【解决方案3】:

      如果您的列表未排序,则两种解决方案都不起作用,它们只会比较相邻的值。我能想到的唯一解决方案是性能非常低效的 O(N^2)。遍历列表并删除每个节点,然后检查列表是否包含等于已删除注释的节点并将其删除,然后重新插入已删除的节点。

      【讨论】:

      • 您是对的,OP 不起作用,但第一本书确实有两个循环,并且适用于未排序的。通过列表的其余部分删除重复项,看看它是如何向前看的。
      • 我想说“两者都行不通”在技术上是正确的!或者至少它是模棱两可的,可能意味着“至少有一个不起作用”
      • 两者都有效,在我的代码中我存储int dataToRemove = head.data; 并删除所有包含数据的节点。我在发布这个问题之前进行了彻底的测试
      猜你喜欢
      • 1970-01-01
      • 2013-07-12
      • 1970-01-01
      • 2020-09-07
      • 1970-01-01
      • 2020-06-09
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多