代码随想录算法训练营第四天 | 链表part02

64 阅读3分钟

代码随想录算法训练营第四天 | 链表part02

24. 两两交换链表中的节点

相邻2个节点进行交换,也设置一个虚拟头节点。

0 -> 1 -> 2

就需要变成

0 -> 2 -> 1

首先第一步需要

0 -> 2,

然后 2 -> 1,

但是1应该指向原先2后面的节点

所以应该首先存储一下1节点以及2节点后面的节点

while(current.next and current.next.next):
    temp = current.next # 存储节点1
    temp1 = current.next.next.next # 存储2节点后面的节点
    current.next = current.next.next # 0 -> 2
    current.next.next = temp # 2 —> 1
    current.next.next.next = temp1 # 1 -> 2节点后面的节点
    current = current.next.next # 让当前节点指向下一次的开头
return dummy_head.next

19.删除链表的倒数第N个节点

思路:快慢指针,快指针先走n+1步,然后和慢指针一起走。

然后走到倒数第N+1个节点的时候,next = next.next

注意:n+1步,是因为删除节点的时候必须走到这个节点的前一个节点。

如果快指针先走n步,那么最后慢指针会指到删除的这个节点,就删不了了。

还有一个更重要的原因,是我们设置了虚拟的头节点。

dummy_head = ListNode(next = head)
fast , slow = dummy_head ,dummy_head
for i in range(n+1):
    fast = fast.next
while fast :
    fast = fast.next
    slow = slow.next
slow.next = slow.next.next
return dummy_head.next

面试题 02.07. 链表相交

注意:数值相同,不代表指针相同。

思路

简单来说,就是求两个链表交点节点的指针

为了方便举例,假设节点元素数值相等,则节点指针相等。

看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:

面试题02.07.链表相交_1

我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:

面试题02.07.链表相交_2

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        dummy_headA = ListNode(next = headA)
        curA = dummy_headA
        dummy_headB = ListNode(next = headB)
        curB = dummy_headB
        countA = 0
        countB = 0
        while(curA.next):
            countA += 1
            curA = curA.next
        while(curB.next):
            countB += 1
            curB = curB.next
        if countA > countB:
            curA = dummy_headA
            curB = dummy_headB
            cha = countA - countB
            for i in range(cha):
                curA = curA.next
            while(curA != curB):
                curA = curA.next
                curB = curB.next
            if (curA == curB):
                return curA
        elif countA < countB:
            curA = dummy_headA
            curB = dummy_headB
            cha = countB - countA
            for i in range(cha):
                curB = curB.next
            while(curA != curB):
                curA = curA.next
                curB = curB.next
            if (curA == curB):
                return curA    
        else :
            curA = dummy_headA
            curB = dummy_headB
            while(curA != curB):
                curA = curA.next
                curB = curB.next
            if (curA == curB):
                return curA

142.环形链表II

别被题目吓到,其实很简单。

追及问题,A每次跑2步,B每次跑1步,然后在环内相遇,找到相遇的位置。

在相遇之后设置一个index1等于相遇的位置,index2等于head的位置。

然后index1 = index2的时候就是进入环内时的节点,return index1即可

如果没有相遇,那就是无环,return None

dummy_head = ListNode(next = head)
fast = dummy_head.next
slow = dummy_head.next
while fast and fast.next:
    fast = fast.next.next
    slow = slow.next
    if fast == slow :
        index1 = fast
        index2 = head
        while index1 != index2:
            index1 = index1.next
            index2 = index2.next
        return index1
return None

一般涉及到 增删改操作,用虚拟头结点都会方便很多, 如果只能查的话,用不用虚拟头结点都差不多。

当然为了方便记忆,统一都用虚拟头结点。