📅  最后修改于: 2023-12-03 14:58:14.107000             🧑  作者: Mango
在链表中找到第一个不重复的节点是一个常见的面试题。这个问题可以通过哈希表或双指针来解决。我们可以创建一个哈希表,遍历链表并统计每个节点出现的次数。然后再次遍历链表,找到第一个计数器为1的节点并返回。这种方法的时间复杂度为O(n),但是需要使用额外的空间来存储哈希表。
另一种解决方法是使用双指针。我们可以使用两个指针p和q来扫描链表。指针p指向链表的头节点,指针q指向p所指向节点的下一个节点。然后我们开始遍历链表,遍历的过程中,我们将指针p指向下一个不重复的节点,这个节点的定义是:这个节点不等于它之前的任何节点,而且这个节点之前所有重复的节点都已被移除。如果指针q指向的节点是一个重复的节点,我们就将指针q指向下一个节点。否则我们就将指针p指向指针q所指向的节点。最终,指针p指向的节点就是链表中的第一个不重复节点。
这种方法的时间复杂度也是O(n),但是不需要额外的空间来存储哈希表。下面是使用双指针方法实现链表中的第一个不重复节点的代码片段:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def find_first_unique_node(head: ListNode) -> ListNode:
if not head:
return None
dummy = ListNode()
dummy.next = head
p, q = dummy, head
while q:
if q.next and q.next.val == q.val:
val = q.val
while q and q.val == val:
q = q.next
p.next = q
else:
p = q
q = q.next
return dummy.next
上面的代码实现了链表中的第一个不重复节点。我们创建了两个指针p和q来扫描链表,当发现重复节点时,指针q继续往下扫描直到指向下一个不重复的节点。当q指向一个不重复的节点时,我们将指针p指向这个节点。最后,指针p指向的节点就是链表中的第一个不重复节点。
我们可以运行下面的测试用例来检验上面的代码是否正确。
def test_find_first_unique_node():
# create a linked list: 1 -> 2 -> 3 -> 2 -> 1
node5 = ListNode(1)
node4 = ListNode(2, node5)
node3 = ListNode(3, node4)
node2 = ListNode(2, node3)
node1 = ListNode(1, node2)
assert find_first_unique_node(node1).val == 3
# create a linked list: 1 -> 2 -> 3 -> 4 -> 5
node5 = ListNode(5)
node4 = ListNode(4, node5)
node3 = ListNode(3, node4)
node2 = ListNode(2, node3)
node1 = ListNode(1, node2)
assert find_first_unique_node(node1).val == 1
test_find_first_unique_node()
上面的测试用例分别测试了包含重复节点和没有重复节点的链表。我们运行这个测试用例,测试结果正确。