leetcode 链表+双指针问题小结

141. 环形链表

在这里插入图片描述
设置两个速度不一样的链表,如果其中他们两个在经过一定的步数(进入环之后,在 n × ∣ 环的大小 ∣ n \times |环的大小| n×环的大小 步后会重合)之后会重合,则说明有环。

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

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        head_i = head
        head_j = head

        while(head_i is not None and head_j is not None):
            head_i = head_i.next
            head_j = head_j.next
            if head_j is None:
                return False
            else:
                head_j = head_j.next
            
            total += 1
            if head_i == head_j:
                return True
        
        return False

142. 环形链表 II

在这里插入图片描述
这里与上一题不同的地方在于需要求得环的入口。
设慢指针的步数为s,则第一次相遇时,快指针的步数为2s=s+nb,其中b为环的长度。化简可以得到s=nb。
在二者相遇之后,我们将快指针回退到head的位置。假设快指针又经过a步到达环的入口,此时慢指针步数为a+s=a+nb,一定也会到达环口。因此只需要再求出这时二者相遇的位置即可。

在这里插入图片描述

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

class Solution(object):
    def detectCycle(self, head):
        if not head:
            return None
        """
        :type head: ListNode
        :rtype: ListNode
        """
        head_slow = head
        head_fast = head

        while(True):
            if not head_fast.next or not head_fast.next.next:
                return None
            head_slow, head_fast = head_slow.next, head_fast.next.next
            if head_slow == head_fast:
                # 第一次相遇
                break

        head_fast = head
        while(head_fast != head_slow):
            head_fast, head_slow = head_fast.next, head_slow.next

        return head_fast

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

在这里插入图片描述

这个让快指针先走n步就可以了。需要注意的是可以设置一个dummy head以处理只有一个node的情况。

# 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 = ListNode(next=head)
        
        # 设置一个dummy head可以帮助处理只有一个节点的情况
        fast, slow = dummy, dummy
        for i in range(n):
            fast = fast.next

        while(fast.next != None):
            slow = slow.next
            fast = fast.next
        slow.next = slow.next.next

        return dummy.next

160. 相交链表

在这里插入图片描述
这一题的主要思路是两个head均设置一个指针,当某一个指针到达终点之后,去到对方的head重新开始走,走到交叉点一定会相遇,因为这时两个指针的路径长度都是a+b+c。
在这里插入图片描述

# 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) -> Optional[ListNode]:

        pointerA = headA
        pointerB = headB
        # 当某一个指针到达终点之后,去到对方的head重新开始走,走到交叉点一定会相遇
        # 因为这时两个指针的路径长度都是a+b+c
        while(pointerA != pointerB):
            pointerA = pointerA.next if pointerA else headB 
            pointerB = pointerB.next if pointerB else headA 

        if pointerA == pointerB and pointerB is not None:
            return pointerA
            
        return None
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值