Leetcode日练笔记30 [Linked List专题] #142 #160 Linked List Cycle II & Intersection of Two Linked Lists

#142 Linked List Cycle II

Given the head of a linked list, return the node where the cycle begins. If there is no cycle, return null.

There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to (0-indexed). It is -1 if there is no cycle. Note that pos is not passed as a parameter.

Do not modify the linked list.

解题思路:

方法1.还是visited存见过的点,再次见就是环入口。

方法2.慢指针和快指针相遇的点与链表开始的点同时往前进1,相遇的地方为环的入口。

方法2的推理过程:

先看环在不在,不在就return None。

在的话,链表开始的点距离环入口为F。而环上有C个点。快指针和慢指针相遇的地方距离环入口为A。A + B = C. B为环减去相遇点剩下的点。

一直快指针步速是慢指针的2倍。所以F+A= (F + A + nC)/2.

推出F + a = nC。当C > F时,n=1,那么C - A = B,B自然也等于F。所以相遇的地方为环的入口。

当C < F 时,那么 F = B + nC. 相遇的点还是环的入口。

# 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]:
        visited = set()
        while head:
            if head in visited:
                return head
            visited.add(head)
            head = head.next
        return None
# 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]:
        slow = fast = slow2 = head
        
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                while slow != slow2:
                    slow2 = slow2.next
                    slow = slow.next
                return slow
        return None

#160 Intersection of Two Linked Lists

 

Given the heads of two singly linked-lists headA and headB, return the node at which the two lists intersect. If the two linked lists have no intersection at all, return null.

For example, the following two linked lists begin to intersect at node c1:

The test cases are generated such that there are no cycles anywhere in the entire linked structure.

Note that the linked lists must retain their original structure after the function returns.

Custom Judge:

The inputs to the judge are given as follows (your program is not given these inputs):

  • intersectVal - The value of the node where the intersection occurs. This is 0 if there is no intersected node.
  • listA - The first linked list.
  • listB - The second linked list.
  • skipA - The number of nodes to skip ahead in listA (starting from the head) to get to the intersected node.
  • skipB - The number of nodes to skip ahead in listB (starting from the head) to get to the intersected node.

The judge will then create the linked structure based on these inputs and pass the two heads, headA and headB to your program. If you correctly return the intersected node, then your solution will be accepted.

 

解题思路:

因为题目希望最好space complexityO(1)。所以还是只能用双指针。

本来我的想法是如果有intersection point的话,那么长短链的尾部一部分是重合的,可以把两个指针放在长短链的最后,往回走,走到不再相同为止的上一个点就是intersection。但是因为这个是单链,所以这样行不通。

参考了solution的解法后,可以把双指针长短链先后走一遍,就会同时到达intersection point。喵喵喵。

# 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]:
        pt1 = headA
        pt2 = headB
        end1 = end2 = 0
        
        while pt1 and pt2:
            if pt1 == pt2:
                return pt1
            
            pt1 = pt1.next
            if pt1 == None and end1 == 0 :
                pt1 = headB
                end1 = 1
                
            pt2 = pt2.next
            if pt2 == None and end2 == 0:
                pt2 = headA
                end2 = 1
        
        return None

长链走完马上重新回到短链,所以设置了指针一旦触尾,即None,马上掉头。但是第二次触尾就该终止while循环了。因此设置了end1和end2关卡。

runtime:

forum里的解法:

class Solution:
    # @param two ListNodes
    # @return the intersected ListNode
    def getIntersectionNode(self, headA, headB):
        if headA is None or headB is None:
            return None

        pa = headA # 2 pointers
        pb = headB

        while pa is not pb:
            # if either pointer hits the end, switch head and continue the second traversal, 
            # if not hit the end, just move on to next
            pa = headB if pa is None else pa.next
            pb = headA if pb is None else pb.next

        return pa # only 2 ways to get out of the loop, they meet or the both hit the end=None

# the idea is if you switch head, the possible difference between length would be countered. 
# On the second traversal, they either hit or miss. 
# if they meet, pa or pb would be the node we are looking for, 
# if they didn't meet, they will hit the end at the same iteration, pa == pb == None, return either one of them is the same,None

 while循环设置的结束条件是两个指针相等。

我没有想到的是即使不存在intersection point的点,长短链都跑一遍,最后指针会同时触尾,即None。这个时候随便输出任一指针,都是None。

确实这样比我的解法更简洁。学到了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值