python 链表总结


链表基础知识

python定义:

class ListNode:
    def __init__(self, val, next=None):
        self.val = val
        self.next = next

删除节点:
在这里插入图片描述
添加节点:
在这里插入图片描述
性能分析:
在这里插入图片描述

移除链表元素

在这里插入代码片
class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        dummy_head = ListNode(next=head)
        cur = dummy_head
        while cur.next:
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return dummy_head.next

设计链表

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • -addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

相当于啥也没给你,全在里面操作。

class ListNode:  # 单链表
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class MyLinkedList:

    def __init__(self):
        self.dummy_head = ListNode()  # 虚拟头
        self.count = 0  # 节点数

    def get(self, index: int) -> int:
        if 0 <= index < self.count:
            cur = self.dummy_head
            for i in range(index + 1):
                cur = cur.next
            return cur.val
        else:
            return -1

    def addAtHead(self, val: int) -> None:
        new_list = ListNode(val)
        new_list.next = self.asummy_head.next
        self.dummy_head.next = new_list
        self.count += 1

    def addAtTail(self, val: int) -> None:
        new_list = ListNode(val)
        cur = self.dummy_head
        while cur.next:
            cur = cur.next
        cur.next = new_list
        self.count += 1

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0:
            self.addAtHead(val)
        elif 0 <= index < self.count:
            new_list = ListNode(val)
            cur = self.dummy_head
            for i in range(index):
                cur = cur.next
            new_list.next = cur.next
            cur.next = new_list
            self.count += 1
        elif index == self.count:
            self.addAtTail(val)
            

    def deleteAtIndex(self, index: int) -> None:
        if 0 <= index < self.count:
            cur = self.dummy_head
            for i in range(index):
                cur = cur.next
            cur.next = cur.next.next
            self.count -= 1

双链表增加了获取index 和直接增加节点的功能。

class LinkNode:  # 双链表
    def __init__(self, val = 0, prev = None, next = None):
        self.prev = prev
        self.next = next
        self.val = val


class MyLinkedList:

    def __init__(self):
        self.dummy_head = LinkNode()
        self.dummy_tail = LinkNode()
        self.dummy_head.next, self.dummy_tail.prev = self.dummy_tail, self.dummy_head
        self.count = 0

    def get_node(self, index):
        if index  < self.count // 2:
            cur = self.dummy_head
            for i in range(index + 1):
                cur = cur.next
            return cur
        else:
            cur = self.dummy_tail
            for i in range(self.count - index):
                cur = cur.prev
            return cur

    def get(self, index: int) -> int:
        if 0 <= index < self.count:
            node = self.get_node(index)
            return node.val
        else:
            return -1

    def addAtHead(self, val: int) -> None:
        self.add_data(val, self.dummy_head, self.dummy_head.next)

    def addAtTail(self, val: int) -> None:
        self.add_data(val, self.asummy_tail.prev, self.dummy_tail)

    def addAtIndex(self, index: int, val: int) -> None:
        if index <= 0:
            self.add_data(val, self.dummy_head, self.dummy_head.next)
        elif self.count < index:
            return
        elif 0 < index < self.count:
            node = self.get_node(index)
            self.add_data(val, node.prev, node)
        elif index == self.count:
            self.add_data(val, self.dummy_tail.prev, self.dummy_tail)
    
    def add_data(self, val, prev_node, next_node):
        new_node = LinkNode(val)
        prev_node.next, next_node.prev = new_node, new_node
        new_node.prev, new_node.next = prev_node, next_node
        self.count += 1

    def deleteAtIndex(self, index: int) -> None:
        if 0 <= index < self.count:
            node = self.get_node(index)
            node.prev.next, node.next.prev = node.next, node.prev
            self.count -= 1

翻转链表

pre = cur 这一步相当于把pre移到cur的位置,原来的节点保持不变

class Solution:  # 迭代
    def reverseList(self, head: ListNode) -> ListNode:
        cur = head
        pre = None
        while cur:
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        return pre

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

  • 定义fast指针和slow指针,初始值为虚拟头结点
  • fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作)
  • fast和slow同时移动,直到fast指向末尾
  • 删除slow指向的下一个节点
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        self.dummy_head = ListNode()
        self.dummy_head.next = head
        slow, fast = self.dummy_head, self.dummy_head
        for i in range(n+1):
            fast = fast.next
        while fast:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        # Tip: 这里要返回self.dummy_head.next,而不是返回head,因为当链表的长度只有1并且删除倒数第一个时head还是存在的。
        return self.dummy_head.next

链表相交

即球两个链表交点节点的指针,注意这里交点不是数值相同,而是指针相同。
方法:求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到和curB末尾对齐的位置,如图:

在这里插入图片描述
比较curA和curB是否相同,如果不相同吗,同时往后移动,如果遇到curA==curB则为碰到交点,否则循环退出返回空指针。

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        curA = headA
        curB = headB
        def get_lens(head):
            count = 0
            while head:
                count += 1
                head = head.next
            return count
        len_A = get_lens(headA)
        len_B = get_lens(headB)
        if len_A > len_B:
            for i in range(len_A - len_B):
                curA = curA.next
        else:
            for i in range(len_B - len_A):
                curB = curB.next
        while curA:
            if curA == curB:
                return curB
            curA = curA.next
            curB = curB.next
        return None

环形链表

  • 判断是否由环
    定义fast和slow指针,从头结点出发,fast指针每次移动两个节点,slow每次移动一个节点,如果有环,就一定会相遇。
  • 如果有环,如何找到这个环的入口
    见代码随想录:index_x从x出发后,从slow和fast交点出发的点index_z一定会和x相遇在环形的起始点
class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        slow, fast = head, head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                curA = head
                curB = slow
                while curA != curB:
                    curA = curA.next
                    curB = curB.next
                return curA
        return None

感谢阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值