所以我在Gayle Lackermaan的《破解编码面试》中查找问题,发现了这个问题:
Write code to remove duplicates from an unsorted linked list
解决方案就是这个
public static void deleteDups (LinkedListNode n){
Hashset<Integer> set = new HashSet<Integer>();
LinkedListNode previous = null;
while(n!=null){
if(set.contains(n.data){
previous.next = n.next;
} else {
set.add(n.data);
previous = n;
}
n = n.next;
}
}
我不明白previous
的意义;previous
的作用域在函数内,因为它是在函数内创建的,对吧?它没有被用来做任何事情,为什么它在那里?此外,以前似乎并没有向前发展;相反,它不是每次迭代都被覆盖吗?
此外,如果我理解Java的按值传递引用风格,那么将一个头节点n传递给一个多次执行n = n.next
的函数,在它返回后不会影响n的值,对吗?如果函数执行了一堆n.next = n
或n.data = 3
呢?这会影响n返回后的值吗?(我想是的)
我已经研究这个函数很长时间了,但我仍然不知道调用它会有什么作用。
这一行就在这里:
previous.next = n.next;
这里有一种魔力,我想因为一个刚开始的程序员没有文档记录而狠狠地打一顿。"上一个"是我们看到的链接列表中的最后一个项目。n
是当前项目。因此,当我们将previous.next设置为n.next时,我们跳过n。这一行有效地从链表中删除了n。它在一个条件中,用来检查我们以前是否看到过这些数据,所以这就是消除重复的魔力。
我们之所以在这里跟踪以前的内容,是为了做到这一点——将上一件事与下一件事联系起来,有效地删除了当前的内容。
如何声明It isn't being used for anything, so why is it there?
请参阅以下内容。。。
if(set.contains(n.data){
previous.next = n.next; // used here
} else {
set.add(n.data);
previous = n; // used here
}
previous
用于保持对当前节点列表中"上一个"节点的引用,以防必须删除当前节点。这是通过将"上一个"节点指向下一个节点而不是当前节点来完成的。
不需要更改传递的引用,因为列表中的第一个元素永远不会是重复的。因此,您只需要删除第一个节点之后的节点。这是通过操作列表中的"下一个"节点而不是"根"来完成的