数据结构与算法-链表必写题汇总(快慢指针、哨兵等)

在这里插入图片描述
想到使用快慢指针法,但是只需要慢指针即可,具体解法见图示。

快慢指针法教学地址为:https://blog.csdn.net/qq_22795223/article/details/104247626

在这里插入图片描述
接下来直接上代码:

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

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        prev = None
        slow = head
        # fast = head
        Next = slow

        if (head is None) or (head.next is None):
            return head

        while(slow != None):
            # fast = fast.next.next
            Next = slow.next
            slow.next = prev
            prev = slow
            slow = Next

        return prev

在这里插入图片描述
一开始想着用一个指针来做,但是发现不行,那么还是可以使用快慢指针法去进行解决,具体分析见图。
在这里插入图片描述
再直接上代码:

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

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if head == None:
            return False

        slow = head
        fast = head

        while((fast != None) and (fast.next != None)):  
        # 奇数和偶数两种情况都不能放过
            slow = slow.next
            fast = fast.next.next
            if (slow == fast):
                return True

        return False

在这里插入图片描述
这题一开始使用快慢指针法的变形即slow和fast均各走一步,但是发现prev指向的是None,最后输出的结果反而是全部为逆序,弄巧成拙了,后来才反应过来,如果prev指向的不是None,指向的是哨兵,那么哨兵则可以直接.next添加下一个结点,这是极其方便的,而且哨兵可以固定住单链表头,最后直接输出哨兵.next,即输出了全部的单链表。
具体见图解:
在这里插入图片描述
在这里插入图片描述
接下来直接上代码,这题还可以用递归的方法去做,这里递归还没有非常完整的学习体系,所以暂且不提:

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

class Solution(object):
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        prehead = ListNode(-1)  # 哨兵
        prev = prehead

        # cur1 = l1 
        # cur2 = l2  不太需要这两个游标
        while (l1 and l2):
            if l1.val <= l2.val:
                prev.next = l1
                prev = l1
                l1 = l1.next
            else:
                prev.next = l2
                prev = l2
                l2 = l2.next

        if l2 != None:
            prev.next = l2
        if l1 != None:
            prev.next = l1
        
        return prehead.next

在这里插入图片描述
有两种方法,第一种方法是两次遍历,第二种方法是快慢指针,我们逐一介绍。

两次遍历

第一次遍历确定长度,然后通过长度L与n的差值,来确定要删除结点的前继结点位置。
第二次遍历到前继结点位置,进行删除目标结点即可。
直接上代码,太简单了:

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

class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        if head.next == None and n == 1:
            return None

        prehead = ListNode(-1)
        prehead.next = head
        pre = prehead

        L = 1

        while (pre.next != None):
            pre = pre.next
            L += 1
        d = L - n
        count = 1
        pre = prehead
        while (count != d):
            pre = pre.next
            count += 1
        
        pre.next = pre.next.next

        return prehead.next

快慢指针

首先slow指针不动,fast指针每次动一次,同时计算slow和fast之间的间隔between;当between-1与n相等时,slow和fast才同时每次移动一次;当fast移动到指向None时,跳出移动的循环;此时的slow指向前继结点,直接删去目标结点即可。

动图网址为:https://pic.leetcode-cn.com/cc43daa8cbb755373ce4c5cd10c44066dc770a34a6d2913a52f8047cbf5e6e56-file_1559548337458

看一下伪代码画图过程:
在这里插入图片描述
接下来上代码:

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

class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        if head.next == None and n == 1:
            return None

        prehead = ListNode(-1)
        prehead.next = head
        slow = prehead
        fast = prehead

        between = 0
        while (between - 1 != n):
            fast = fast.next
            between += 1

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

        slow.next = slow.next.next

        return prehead.next

在这里插入图片描述
快慢指针即可解决
在这里插入图片描述
最后直接上代码:

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

class Solution(object):
    def middleNode(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        # prev = head  没必要了
        slow = head
        fast = head
        # count = 0  没必要了

        while fast != None and fast.next != None:
            # count += 1  没必要了
            slow = slow.next
            fast = fast.next.next      

        # while (count != 0):
        #     prev = prev.next
        #     count -= 1

        # return prev
        return slow  # 直接返回slow即可
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xu_Wave

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值