算法训练记录day4

本文介绍了四种针对链表的算法问题解决方案:1)两两交换链表中的节点,通过设置虚拟头节点和双指针实现;2)删除链表的倒数第N个节点,使用快慢指针法;3)找到两个链表的相交节点,通过计算长度差调整指针位置;4)检测并找到环形链表的入口节点,利用快慢指针相遇点。
摘要由CSDN通过智能技术生成

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

题目

思路

每两个节点交换一下。如果节点个数为奇数,则最后一个节点不用交换

# 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
"""指针的下一个为空(对应奇数),指针的下下一个为空(偶数)"""
        while (cur.next!=None  and cur.next.next !=None):  
"""cur每次应该出现在两个被交换节点的前一个节点,如cur=dummy_head,在头节点之前"""
            temp = cur.next                 # 在交换时,要保存1号节点和3号节点
            temp1 = cur.next.next.next     # 防止其节点丢失
            cur.next = temp.next           # 让虚拟指向2号   虚拟到1号断了  其他正常
            temp.next.next = temp            # 让2号指向1号    2号到3号断了
            temp.next = temp1                # 让1号指向 3号     1号到2号断了
            cur = cur.next.next               # 在让cur 移到3号前
            # 重复上述过程,循环
        return dummy_head.next

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

题目

思路

借助两个指针,让快指针到达最后一个节点时,慢指针正好在被删节点前

# 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_node = ListNode(next = head)
        fast = dummy_node
        slow = dummy_node
        while (n and fast!=None):    # 快指针先向前移动n个节点 ,并且非空
            fast = fast.next
            n-=1
        """让快、慢指针一起走,直到快指针到最后一个节点,快慢指针相差n个节点"""
        while (fast.next!=None):      # 这个判断条件,使得慢指针正好在被删除节点前一个节点
        """如果是while (fast!=None) 慢指针就落在了被删节点上"""
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next   # 删除操作
        
        return dummy_node.next

三、链表相交

题目

思路

# 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:
        curA= headA
        curB= headB
        lenA = 0
        lenB = 0
        while (curA!=None):   # 找到其长度
            lenA+=1
            curA = curA.next
        while (curB!=None):   # 找到其长度
            lenB+=1
            curB = curB.next
        curA = headA        # 重新赋值 让其回到头节点
        curB = headB
        if lenA > lenB:   # 比较长度 后面的操作是基于lenA > lenB,统一条件,处理更方便
            pass
        else :           # 在这种情况下,将两个单链表调换一下,使得lenA > lenB   
            lenA , lenB = lenB,lenA
            headA , headB = headB,headA
            curA,curB = curB,curA
        """这段操作使得A永远是长的"""
        n = lenA - lenB
        while n:                        # 先让curA移动n个节点 此时与curB(头节点)对齐了
            curA = curA.next
            n -= 1
        while(curA):                   # 只要curA不为空
            if curA != curB:           # 如果节点不相等  同时移动 A 和 B
                curA = curA.next
                curB = curB.next
            else:
                return curA            # 相等 则返回节点
        return None                    # 如果curA为空了 退出循环,即没找到相等的 返回None

四、环形链表II

题目

思路

# 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!= None and fast.next!=None):       # 这个是判断是否为环形
            fast = fast.next.next     # 快指针  不满足条件,退出循环,即不是环形
            slow = slow.next
            if fast == slow :     #相遇的条件
                index1 = head     #从头开始移动
                index2 = fast     #从相遇点开始移动
                while index1 != index2:
                    index1 = index1.next   # 让其移动,最终会在节点相遇
                    index2 = index2.next
            """最终相等的点,即为进入环形的节点"""
                return index1
        return None                                     # 不是环形

x = z 这是一个特解。简单理解。即x = index1.next ,z = index2.next

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值