Java 在链表操作中使用sentinel节点
我在Leetcode上解决了一个问题,通过提供的解决方案,我遇到了“哨兵/虚拟节点”的概念。在某些情况下,使用这样的节点可以简化链表中的操作,例如空列表或包含一个元素的列表等 问题描述是- 从具有值的整数链表中删除所有元素 瓦尔 例如: 输入:1->2->6->3->4->5->6,val=6输出:1->2->3->4->5 给出的解决方案是-Java 在链表操作中使用sentinel节点,java,data-structures,linked-list,reference,Java,Data Structures,Linked List,Reference,我在Leetcode上解决了一个问题,通过提供的解决方案,我遇到了“哨兵/虚拟节点”的概念。在某些情况下,使用这样的节点可以简化链表中的操作,例如空列表或包含一个元素的列表等 问题描述是- 从具有值的整数链表中删除所有元素 瓦尔 例如: 输入:1->2->6->3->4->5->6,val=6输出:1->2->3->4->5 给出的解决方案是- class Solution { public ListNode removeElements(ListNode head, int val) {
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode sentinel = new ListNode(0);
sentinel.next = head;
ListNode prev = sentinel, curr = head;
while (curr != null) {
if (curr.val == val) prev.next = curr.next;
else prev = curr;
curr = curr.next;
}
return sentinel.next;
}
}
让我们考虑一下这个链表——
1->1->2->3->NULL
,要删除的节点的值为1
因此,结果列表应该是2->3->NULL
,该列表的head
指向2
在这一行中-sentinel.next=头部
我们将sentinel
作为列表中的第一个节点,它的next
节点是“head”,如下所示-
0->1->1->2->3->NULL
- 请注意,
仍然指向head
(列表中第一个值为1的节点)1
- 在while循环开始之前,我们将
设置为prev
,将sentinel
设置为curr
head
- 在循环过程中,
和prev
沿列表移动,都指向列表中的其他节点。请注意,curr
仍然指向第一个1head
- 循环之后,
指向列表中的最后一个节点(值为3),而prev
变为curr
null
- 但是,
仍然指列表中的第一个节点(值为1),而head
指的就是这个节点。因此,当我们运行sentinel。next
->时,我们得到了对列表中第一个节点的引用(值为1),其return sentinel.next
属性不指向任何其他节点。这是一个节点本身next
ListNode
应该引用值为2
的节点,而不是1
这是基于我对Java中引用如何工作的了解。因为,当我们从这个开始的时候-
ListNode sentinel=新的ListNode(0);
sentinel.next=头部;
ListNode prev=哨兵,curr=头部;
我们得到这样的东西-[sentinel]->[head]
,其中prev
指向sentinel
和curr
指向head
但问题是prev
和curr
在列表期间都会更改引用,而sentinel
和head
则不会。因此,sentinel.next
仍然指向旧的头部
编辑1
为了让我的问题更清楚,这里有一个例子。我想知道的是,sentinel.next
如何引用值为2
的节点?开始时,sentinel.next
被设置为head
,这在任何地方都没有改变。因此,sentinel.next
应该引用列表的原始头
——值为1的节点
编辑2
我想我现在明白了。更改发生在此行prev.next=curr.next代码>
因为prev
和sentinel
都引用相同的列表元素(在这个阶段),sentinel.next
设置正确。
- 我想这可能是不正确的:
当我们运行return sentinel.next->时,我们首先得到一个对此的引用
列表中的节点
prev
对于前两个值不会移动,我猜。仅将其链接移动到下一个节点
- 另一件事是sentinel是
最终版
,不会改变:
- 也许我们应该注意到,我们没有删除任何值(值在内存中),我们只是更改链接列表的链接
- 最后,我们只对链表的标题感兴趣,它将是
sentinel。接下来
,我们不想看到prev
在哪里
迭代地
1和1之间的链接仍然存在,忘了画它。是的,prev
对于两个1
s不移动,但是对于2
和3
,所以当循环结束时,prev
处于3
。我添加了一个print语句,返回的值显示为“2”。屏幕截图-但这是我的问题-sentinel.next
如何引用2
,当它应该引用原始头部时。
class Solution {
public ListNode removeElements(
final ListNode head,
final int val
) {
final ListNode sentinel = new ListNode(0);
sentinel.next = head;
ListNode prev = sentinel;
ListNode curr = head;
while (curr != null) {
if (curr.val == val) {
prev.next = curr.next;
}
else {
prev = curr;
}
curr = curr.next;
}
return sentinel.next;
}
}
class Solution {
public ListNode removeElements(ListNode head, int val) {
if (head == null)
return null;
head.next = removeElements(head.next, val);
return head.val == val ? head.next : head;
}
}