📜  链表中的第一个不重复(1)

📅  最后修改于: 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()

上面的测试用例分别测试了包含重复节点和没有重复节点的链表。我们运行这个测试用例,测试结果正确。