想躺平又躺不平的day03


两两交换链表中的节点

  给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

  我感觉这道题首先应该明确cur初始化指向虚拟头节点还是头节点,可以手画链表结构图知道应该是指向虚拟头节点才能进行后续两两节点的交换。还需要注意的就是遍历条件的确定,由于我们是从虚拟头节点开始遍历,交换往后两个节点,也就是说当cur指向某个节点,它后面没有节点(链表节点数为偶数)或者只有一个节点(链表节点数为奇数)时则意味着遍历结束。即,遍历条件为cur.next不为null且cur.next.next不为null。(ps:cur.next的判断要在cur.next.next判断之前以防止出现空指针异常)
  然后就是交换过程,按如下的步骤进行交换,且cur指针更新规则为cur=cur.next.next。
交换过程示意图

class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        dummy_head = ListNode(next=head)
        cur = dummy_head
        while cur.next and cur.next.next:
            tmp1 = cur.next
            tmp2 = cur.next.next.next
            cur.next = cur.next.next  #步骤一
            cur.next.next = tmp1  #步骤二
            tmp1.next = tmp2  #步骤三:注意这里是tmp1.next而不是cur.next(因为此时cur.next已经改变)
            cur = cur.next.next  
        return dummy_head.next       

  将步骤二与步骤三顺序调换一下,可以只用一个临时指针。

class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        dummy_head = ListNode(next=head)
        cur = dummy_head
        while cur.next and cur.next.next:
            tmp1 = cur.next
            cur.next = cur.next.next  #步骤一
            tmp1.next = tmp1.next.next #步骤三:注意这里是tmp1.next而不是cur.next(因为此时cur.next已经改变)
            cur.next.next = tmp1  #步骤二
            cur = cur.next.next  
        return dummy_head.next 

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

  给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

这几天以来第一道独立思考做出来的题目,感觉妙不可言!鼓掌啪啪啪(咳咳咳注意戒骄戒躁)

class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        dummy_head = ListNode(next=head)
        cur = dummy_head
        while cur.next:
            cur_tmp = cur
            for _ in range(n):
                cur_tmp = cur_tmp.next
            if cur_tmp.next == None:
                cur.next = cur.next.next
                break
            cur = cur.next
        return dummy_head.next

  做到这儿,感觉链表的题目最重要的一点就是画图,能够清晰地知道算法过程,还有就是明确指针的初始化以及遍历条件。这样,基本就没多大问题了。(如果后面的题目没做出来,当我没说)

链表相交

  两个单链表的头节点headA和headB,找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回null。
算法示意图
这里的逻辑:两个链表相交,在相交节点之前有多少个节点是未知的,但是从相交节点到尾节点对于两个链表来说是完全相等的。也就是说,我们可以求出两个链表的长度,对于长链表来说,只用从后一段长度为短链表那么长的地方开始遍历。也可以画种思路理解:从头到相交节点的数量不确定,但是从尾到相交节点的两个链表是完全一致的。

基于以上分析,我们得到长链表的初始遍历节点后,然后令短链表从头开始,同时遍历两个链表,直到两个链表的当前节点相等即为相交节点。

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        ## 获取链表长度
        cur = headA
        lenA = 0
        while cur:
            lenA += 1
            cur = cur.next
        cur = headB
        lenB = 0
        while cur:
            lenB += 1
            cur = cur.next
        
        curA = headA
        curB = headB
        ## 令B链表固定为长链表
        if lenA > lenB:
            curA,curB = curB,curA
            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

环形链表(好难)

  给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回null。

【开始这道题的复盘之前,需要做足万全的心理准备,我在看卡哥视频讲解的时候,就觉得有一种深深的无力感,我觉得这种逻辑我自己完全没有独立思考出来的能力,而且可能遇到类似思想的题目极大可能还是做不出来。】
  首先,两个步骤:

  1. 判断是否有环:用两个指针,一个每次跨越两个节点快指针,一个每次跨一个节点的慢指针,那么如果有环的话这两个指针一定会相遇。
  2. 判断环的入口:假设头节点到环入口节点数为x,环入口节点到两个指针相遇节点数为y,相遇节点到环形入口节点数为z。(如下图所示为快慢指针走过的节点数,且快指针为慢指针速度的两倍,即x+y+n(y+z)=2(x+y),化简可得x=(n-1)(y+z)+z,即x等于若干圈环形加上z。)
      敲重点敲重点: x等于若干圈环形加上z,那么在头节点和相遇节点分别定义两个指针,逐节点遍历相遇的点即为环形入口节点。(妙不妙咱们就是说,看到这有一种酣畅淋漓之后的无力感,感慨这里算法逻辑,以我这颗平平无奇的大脑是没办法想出来的。)
    循环链表环形入口判断示意图
class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        fast = head
        slow = head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                index1 = fast #相遇节点
                index2 = head #头节点
                while index1 != index2:
                    index1 = index1.next
                    index2 = index2.next
                return index1
        return None
  • 10
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值