【leetcode专题系列】链表

82 删除排序链表中的重复元素 II

在这里插入图片描述两个思路,一个是另外建立一个列表,每次赋值。或者在原链表上进行修改。第一个思路更加清晰,第二个思路更省空间。

对于找到不重复的链表也有两个思路,一个是使用标志位,一个是采用存储重复临时元素。

方法一:构建新链表+移动指针

class Solution(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head or not head.next:
            return head
        node = ListNode(0)
        ans  = node
        
        flag = 0
        while head and head.next:
        	# 首次遇到重复
            if head.val == head.next.val:
                flag = 1
            # 当前重复结束,但是不知道下一个是否重 
            elif flag == 1 and head.val != head.next.val:
                flag = 0
             # 当前不重复,且下一个和目前的不重复
            elif flag == 0 and head.val != head.next.val:
                node.next = ListNode(head.val)
                node = node.next
            head = head.next
		# !!!注意,可能需要补上最后一个,当前不重复,且后一个是None
        if flag == 0:
            node.next = ListNode(head.val)
            
        return ans.next

如果才有原地修改也可以:

class Solution(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head or not head.next:
            return head
        ans = ListNode(0)
        curr = head
        node = ans
        while curr and curr.next:
            if curr.val == curr.next.val:
                temp = curr.val
                while curr.next and curr.next.val == temp:
                    curr = curr.next
                # !! 重要,可以防止最后没有结尾
                node.next = curr.next
            else:
                node.next = curr
                node = node.next
            curr = curr.next   
        return ans.next

一定要注意每次操作完都要给node.next一个交代,否则出大问题

86 分割链表

在这里插入图片描述

class Solution(object):
    def partition(self, head, x):
        """
        :type head: ListNode
        :type x: int
        :rtype: ListNode
        """
        if not head or not head.next:
            return head
        small = small_head = ListNode(0)
        large = large_head = ListNode(0)
        while head:
            if head.val<x:
                small.next = head
                small = small.next
            else:
                large.next = head
                large = large.next
            head = head.next
        small.next = large_head.next
        large.next = None
        return small_head.next

复杂度分析

时间复杂度: O ( N ) O(N) O(N),其中N是原链表的长度,我们对该链表进行了遍历。
空间复杂度: O ( 1 ) O(1) O(1),我们没有申请任何新空间。值得注意的是,我们只移动了原有的结点,因此没有使用任何额外空间。

92 反转链表II

在这里插入图片描述借助这道题,我们来总结一下反转链表那些事。
首先贴上迭代的方法:

class Solution(object):
    def reverseBetween(self, head, m, n):
        """
        :type head: ListNode
        :type m: int
        :type n: int
        :rtype: ListNode
        """
        dummy = ListNode(-1)
        dummy.next = head
        pre = dummy
        # 找到翻转链表部分的前一个节点, 1->2->3->4->5->NULL, m = 2, n = 4 指的是 节点值为1
        for _ in range(m-1):
            pre = pre.next
        # 用双指针,进行链表翻转
        node = None
        cur = pre.next
        for _ in range(n-m+1): # 这个循环的末尾太关键了
            cur.next, node, cur = node, cur, cur.next
        # 将翻转部分 和 原链表拼接 此时,cur是反转之后的第一个,也就是5
        pre.next.next = cur ## pre.next 是2 是反转的开头,也是反转结束的末尾

        pre.next = node 
        return dummy.next

具体整理

203 删除链表元素

在这里插入图片描述

class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        pre = ListNode(0)
        ans = pre
        pre.next = head
        # 注意逻辑!!如果next需要被删除,删除以后本次不前进,否则会导致跳了一个判断。
        while pre.next:
            if pre.next.val == val:
                pre.next = pre.next.next
            else:
                pre = pre.next
        return ans.nex
  • 需要注意,如果next需要被删除,删除以后本次不前进,否则会导致跳了一个判断。
  • 用人为加入头节点的方法可以避免一些问题。

206 反转链表

在这里插入图片描述首先是迭代的方法,推荐作为一个模块记住:

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        prev = None
        # 遍历链表
        while head:
            head.next, prev, head = prev, head, head.next
        return prev

可以直接背下来。

需要特别注意完成循环以后,prev是反转以后链表的头,head实际指向是超出范围的第一个(None)。

递归

class Solution(object):
# 输入一个节点 head,将「以 head 为起点」的链表反转,并返回反转之后的头结点。
	def reverseList(self, head):
		"""
		:type head: ListNode
		:rtype: ListNode
		"""
		# 递归终止条件是当前为空,或者下一个节点为空
		if not head or not head.next:
			return head
		# 这里的cur就是最后一个节点
		cur = self.reverseList(head.next)
		# 如果链表是 1->2->3->4->5,那么此时的cur就是5
		# 而head是4,head的下一个是5,下下一个是空
		# 所以head.next.next 就是5->4
		head.next.next = head
		# 防止链表循环,需要将head.next设置为空
		head.next = None
		# 每层递归函数都返回cur,也就是最后一个节点
		return cur
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值