第四天| 24. 两两交换链表中的节点 , 19.删除链表的倒数第N个节点 , 160. 链表相交 142.环形链表II

文章介绍了四个链表相关的编程问题:两两交换链表节点、删除链表的倒数第N个节点、找出链表的相交节点以及检测环形链表。解决方案中强调了dummynode的使用、快慢指针法以及对链表长度的计算,这些技巧能简化问题处理并提高效率。
摘要由CSDN通过智能技术生成

今天还是链表专题,相对于昨天链表的ood题,今天的逻辑相对清晰.

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

这道题充分说明了做dummy node的重要性.如果不做,就要非常详细的具体情况讨论,如果做了则会事半功倍. 还有一个迷惑的点在于要移动三个指针并不是两个.如果以两个为一组的话,这道题还涉及到了组与组之前的联系关系,需要移动指针

Way1:

基本思路很明确,定义三个指针即pre,cur, 和pos. 每次循环(判断pre.next and pre.next.next是否存在) 都要进行指针cur和pos的指针互换,同时最后不要忘记pre.next也要发生变动.在这之后移动pre进行下次循环

class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        dummy=ListNode()
        dummy.next=head
        pre=dummy
        while pre.next and pre.next.next:
            cur=pre.next
            pos=pre.next.next

            cur.next=pos.next
            pos.next=cur
            pre.next=pos

            pre=pre.next.next
        return dummy.next

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

这道题其实有两种吧方法去做,各有优略

Way1:

这种方式比较简单粗暴,基本思路就是先算出一共有多少个node,然后移动size-n-1词,然后改变next即可

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        cur=head
        size=0
        while cur:
            cur=cur.next
            size+=1
        if size==n:
            return head.next
        cur=head
        for _ in range(size-n-1):
            cur=cur.next
        cur.next=cur.next.next
        return head

Way2:

使用two pointer的方法.通过fast先移动n次然后以fast作为铆钉,去移动slow直到fast为空,这样的话就凭空创造了找到了倒数第n+1的node

dummy=ListNode()
        dummy.next=head
        fast=dummy
        slow=dummy
        for _ in range(n+1):
            fast=fast.next
        while fast:
            fast=fast.next
            slow=slow.next
        slow.next=slow.next.next
        return dummy.next

160. 链表相交

这道题也是比较灵活的题,方法上看是否要借助array或者set来记录值

Way1:

相对来说简单暴力,遍历A的过程中记录所有的值,然后遍历B的过程中去找第一个在A中的值

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        one = headA
        xs=set()
        while one:
            xs.add(one)
            one=one.next
        two = headB
        while two:
            if two in xs:
                return two
            two=two.next
        return None

Way2:

这种方法就要考虑的很多了.首先要判断是什么时候相交可能出现: 很明显相交是在较长的字符串的第lena-lenb的地方开始的,在这之后只要移动两个list的指针并且每次判断是否相等即可

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        lena,lenb=0,0
        cur=headA
        while cur:
            lena+=1
            cur=cur.next
        cur=headB
        while cur:
            lenb+=1
            cur=cur.next
        cura,curb=headA,headB
        if lena > lenb:
            curb,cura=cura,curb
            lena,lenb=lenb,lena
        for _ in range(lenb-lena):
            curb=curb.next
        while cura:
            if cura==curb:
                return cura
            cura=cura.next
            curb=curb.next
        return None

142.环形链表II

这道题没有什么捷径,首先要进行数学分析,通过分析路径我们得知 x=(n-1)(y+z)+z, 然后即可确定方法,

Way1:

先利用快慢指针确定环,然后再重置slow=head去寻找环的起始位置

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow=head
        fast=head
        while fast and fast.next:
            slow=slow.next
            fast=fast.next.next
            if slow==fast:
                break
        if not fast or not fast.next:
            return None
        slow=head
        while slow!=fast:
            slow=slow.next
            fast=fast.next
        return fast

链表专题总结:

从方法上来说two pointer是最常见的. 一些小的tips是非常重要的,比如建立dummy node,比如进行数学路径分析.这些tips不仅能够简化需要考虑的情况,而且可以帮助确定方法.除此之外, 链表的node的数量是非常重要的,一般来说遇到链表题,首先先求个node的总数.这和array一般先做个排序是异曲同工之妙的.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值