代码随想录算法训练营第五天 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II、总结

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

题目链接:24. 两两交换链表中的节点 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——24. 两两交换链表中的节点
视频讲解:帮你把链表细节学清楚! | LeetCode:24. 两两交换链表中的节点_哔哩哔哩_bilibili

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        dummy_head = ListNode(next = head)
        cur = dummy_head

        # 遍历停止条件:偶数节点cur.next不为空,奇数节点cur.next.next不为空
        # 先判断cur.next再判断cur.next.next为了防止空指针异常报错
        while cur.next != None and cur.next.next != None:
            # 定义两个临时节点,存储节点1和节点3.不保存节点2因为此时已经变成cur.next了
            temp = cur.next
            temp1 = cur.next.next.next

            # 交换节点
            cur.next = cur.next.next
            cur.next.next = temp
            temp.next = temp1
            cur = cur.next.next
        
        return dummy_head.next

Notes:cur需要指向将要操作的两个节点的前一个节点,如:要操作3、4,cur则需要指向2。初始cur指向定义的虚拟节点。

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

题目链接:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——19.删除链表的倒数第N个节点
视频讲解:链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点_哔哩哔哩_bilibili

Note:cur指针要指向操作节点的前一个节点

思路:双指针法,快指针先走n+1步,然后快慢指针同时移动,当快指针指向None时,慢指针指向的就是删除节点的前一个节点。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        dummy_head = ListNode(next = head)
        fast = dummy_head
        slow = dummy_head

        # 快指针走n+1步
        for i in range(n+1):
            fast = fast.next

        # 同时移动两个指针
        while fast:
            slow = slow.next
            fast = fast.next

        # 删除节点
        slow.next = slow.next.next
        
        return dummy_head.next

三、面试题 02.07. 链表相交

题目链接:面试题 02.07. 链表相交 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——面试题 02.07. 链表相交

思路:让A B两个链表尾部对齐,后两个指针也对齐开始查找,找到相同的就返回

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

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        # 初始化A B链表长度
        len_A, len_B = 0, 0

        # 获取A链表长度
        cur_A = headA
        while cur_A:
            cur_A = cur_A.next
            len_A += 1

        # 获取B链表长度
        cur_B = headB
        while cur_B:
            cur_B = cur_B.next
            len_B += 1

        # 复位cur_A, cur_B指向headA, headB
        cur_A, cur_B = headA, headB

        # 分两种情况A比B长
        if len_A > len_B:
            # 让两个链表尾部对齐
            for i in range (len_A - len_B):
                cur_A = cur_A.next
            # 开始遍历    
            while cur_A:
                # 如果两个相等则返回交点
                if cur_A == cur_B:
                    return cur_A
                # 否则继续遍历
                else:
                    cur_A = cur_A.next
                    cur_B = cur_B.next
            # 没有交点返回空集
            return None

        else:
            for i in range (len_B - len_A):
                cur_B = cur_B.next
            while cur_B:
                if cur_B == cur_A:
                    return cur_B
                else:
                    cur_A = cur_A.next
                    cur_B = cur_B.next
            return None

四、142.环形链表II

题目链接:142. 环形链表 II - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——142.环形链表II
视频讲解:把环形链表讲清楚! 如何判断环形链表?如何找到环形链表的入口? LeetCode:142.环形链表II_哔哩哔哩_bilibili

判断是否有环:双指针法,快指针每次走两个节点,慢指针一次走一个节点,两个指针一定会在环内相遇。
找环的入口:相遇点和头节点同时以相同速度分别出发一个指针 index1、index2,相交点就是环的入口,具有推导见文章讲解。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 定义两个指针
        fast = head
        slow = head

        # 移动快慢指针
        while fast and fast.next:       # 终止条件为快指针或快指针下一个点为空,因为快指针一次跳两步,要保证fast.next不为空
            fast = fast.next.next
            slow = slow.next

            # 判断是否有环,也就是快慢指针是否能相遇
            if slow == fast:
                index1 = fast   # 从相遇节点走,index2 = slow也可以
                index2 = head   # 从头走

                # 两个index相遇时候终止
                while index1 != index2:
                    index1 = index1.next
                    index2 = index2.next
                return index1

        return None

五、总结

代码随想录 (programmercarl.com)——链表总结

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值