剑指 Offer 最优题解系列python--链表

学习笔记

1. 反转链表(200718)

1.反转链表

方法1:双指针

  1. 定义两个指针: pre和 cur ;pre 在前 cur在后。
  2. 每次让 prepre 的 next 指向 cur ,实现一次局部反转
  3. 局部反转完成之后, pre 和 cur 同时往前移动一个位置
  4. 循环上述过程,直至 pre 到达链表尾部
    在这里插入图片描述
# 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
        """
        last = None
        while head:
            head.next, last, head = last, head, head.next
        return last

在这里插入图片描述

2.链表中倒数第k个结点(200719)

2.链表中倒数第k个结点
解题思路
在这里插入图片描述

算法流程:

  • 初始化: 前指针 former 、后指针 latter ,双指针都指向头节点 head​ 。
  • 构建双指针距离: 前指针 former 先向前走 k步(结束后,双指针 former 和 latter 间相距 k步)。
  • 双指针共同移动: 循环中,双指针 former 和 latter 每轮都向前走一步,直至 former 走过链表 尾节点 时跳出(跳出后, latter 与尾节点距离为 k-1,即 latter 指向倒数第 k 个节点)。
  • 返回值: 返回 latter 即可
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getKthFromEnd(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        former,later = head,head
        for _ in range(k):
            if not former: return
            former=former.next
        while(former):
            former,later = former.next,later.next
        return later

在这里插入图片描述

复杂度分析:
时间复杂度 O(N) : NN 为链表长度;总体看, former 走了 N 步, latter 走了 (N-k)步。
空间复杂度 O(1) : 双指针 former , latter 使用常数大小的额外空间

3.合并两个排序的链表(200720)

3.合并两个排序的链表

# 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
        """
        cur = dum = ListNode(0)
        while l1 and l2:
            if(l1.val < l2.val):
                cur.next, l1 = l1, l1.next
            else:
                cur.next, l2 =l2, l2.next
            cur = cur.next
        cur.next = l1 if l1 else l2
        return dum.next

在这里插入图片描述
复杂度分析:

  • 时间复杂度 O(M+N) : M, N分别为链表l1,l2的长度,合并操作需遍历两链表。
  • 空间复杂度 O(1) : 节点引用 dum , cur使用常数大小的额外空间。

4.复杂链表的复制(200721)

4.复杂链表的复制
题意理解
本题的意思是复制一个链表并返回,这个链表与一般链表不同的是多了一个 random 指针。
在这里,复制的意思是指 深拷贝(Deep Copy),类似我们常用的“复制粘贴”,事实上,与此对应的还有 浅拷贝,它们的区别是:
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

"""
# Definition for a Node.
class Node:
    def __init__(self, x, next=None, random=None):
        self.val = int(x)
        self.next = next
        self.random = random
"""
class Solution(object):
    def copyRandomList(self, head):
        """
        :type head: Node
        :rtype: Node
        """
        return copy.deepcopy(head)

这段代码太羞耻了。后续更其他方法。
在这里插入图片描述

5.两个链表的第一个公共节点(200722)

5.两个链表的第一个公共节点
解题思路:

  • node1向终点奔跑,若到终点返回headB,重新向终点奔跑
  • node2同理
  • 两个人的速度相同,距离相同(若无交点,则两人都在最后A和B的null邂逅。若有交点,则在途中邂逅)
    在这里插入图片描述
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        node1, node2 = headA, headB
        while node1 != node2 :
            node1 = node1.next if node1 else headB
            node2 = node2.next if node2 else headA
        return node1

在这里插入图片描述
复杂度分析

  • 时间复杂度:O(M+N)。
  • 空间复杂度:O(1)。

6.删除链表中结点(200723)

6.删除链表中结点
解题思路
在这里插入图片描述

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution(object):
    def deleteNode(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        if head.val == val :
            return head.next
        pre,cur = head, head.next
        while cur and cur.val!= val:
            pre,cur=cur,cur.next
        if cur:
            pre.next = cur.next
        return head

在这里插入图片描述
复杂度分析:

  • 时间复杂度 O(N)O(N) : N为链表长度,删除操作平均需循环 N/2 次,最差 N次。
  • 空间复杂度 O(1) : cur, pre 占用常数大小额外空间。

7.删除链表中重复的结点(200723)

删除链表中重复的结点
解题思路:

  • 为了防止第一个节点就是重复节点,需要初始化一个新的头节点;
  • 其他参照删除链表结点来做
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def deleteDuplication(self, pHead):
        # write code here
        if pHead == None or pHead.next == None:
            return pHead
        head = ListNode(0) # 为了防止第一个节点就是重复节点,重新弄个头节点
        head.next = pHead
        pre = head # 当前节点的前一个节点
        cur = pHead # 当前节点
        nex = None # 当前节点的后一个节点
        while cur != None and cur.next != None:
            nex = cur.next
            if cur.val == nex.val:
                while nex != None and nex.val == cur.val:
                    nex = nex.next
                pre.next = nex
                cur = nex
            else:
                pre = cur
                cur = cur.next
        return head.next

链表中环的入口结点

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值