从未排序的链表中删除重复项,破解编码面试

时间:2016-03-07 11:57:15

标签: java data-structures linked-list

我正在阅读这本书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空间/时间复杂度?

谢谢!

3 个答案:

答案 0 :(得分:1)

您的代码如何应对1,000,000个唯一项目的列表?

假设没有编译器或运行时优化,您的代码将堆栈溢出。

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

答案 1 :(得分:1)

就复杂性而言,在我看来,两个实现都会产生O(n ^ 2)复杂度,因为迭代答案涉及嵌套循环,而你的涉及一个函数在一个内部递归调用n次循环执行n次。

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

答案 2 :(得分:0)

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

相关问题