【代码随想录】d3-链表part01-python

1. 链表理论基础

什么是链表?

  • 链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
  • 链表的入口节点称为链表的头结点也就是head。
    在这里插入图片描述

1.1.链表的定义

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

1.2. 链表的类型

  • 单链表
    • 单链表中的指针域只能指向节点的下一个节点
      在这里插入图片描述
  • 双链表
    • 每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点
    • 既可以向前查询也可以向后查询
      在这里插入图片描述
  • 循环链表
    • 链表首尾相连
      在这里插入图片描述

1.3.链表的存储方式

  • 数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。
  • 链表是通过指针域的指针链接在内存中各个节点。
  • 所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。

1.4.链表的操作

  • 删除节点
    • 修改链表指针指向即可,删除后的节点python中会自动释放内存
    • 删除D节点,如图所示:
      在这里插入图片描述
    • 只要将C节点的next指针 指向E节点就可以了
  • 添加节点
    • 可以看出链表的增添和删除都是O(1)操作,也不会影响到其他节点
    • 但是要注意,要是删除第五个节点,需要从头节点查找到第四个节点通过next指针进行删除操作,查找的时间复杂度是O(n)
      在这里插入图片描述

1.5链表与数组对比

  • 数组在定义的时候,长度就是固定的,如果想改动数组的长度,就需要重新定义一个新的数组。
  • 链表的长度可以是不固定的,并且可以动态增删, 适合数据量不固定,频繁增删,较少查询的场景
    在这里插入图片描述

2.203.移除链表元素

2.1 题目及讲解

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

题目链接:https://leetcode.cn/problems/remove-linked-list-elements/description/
讲解视频:https://www.bilibili.com/video/BV18B4y1s7R9/?spm_id_from=333.788&vd_source=d49b1b867faa78fdf891abde70b7422f
文字讲解:https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html

2.2 代码实现

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        dummy_head = ListNode(next=head) # 定义虚拟节点
        cur = dummy_head
        while cur.next: # 遍历除虚拟节点之后的所有节点,尾节点的next为null,循环结束
            if cur.next.val == val: 
                cur.next = cur.next.next #下一节点的值如果等于目标值,那么循环时跳过下个节点,直接到下下个节点
            else:
                cur = cur.next 
        return dummy_head.next            

3.707.设计链表

3.1 题目及讲解

你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始

题目链接:https://leetcode.cn/problems/design-linked-list/description/
视频讲解:https://www.bilibili.com/video/BV1FU4y1X7WD/?spm_id_from=333.788&vd_source=d49b1b867faa78fdf891abde70b7422f
文字讲解:https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html

3.2 代码实现

class ListNode:
    def __init__(self,val=0, next=None):
        self.next = next
        self.val = val
class MyLinkedList:
    def __init__(self):
        self.dummy_head = ListNode()
        self.size = 0

    def get(self, index: int) -> int:
        if index <0 or index >= self.size:
            return -1
        cur = self.dummy_head.next
        count = 0
        while count < index:  # 循环遍历到cur等于index的时候输出val
            count += 1
            cur = cur.next
        return cur.val

    def addAtHead(self, val: int) -> None:
        # self.dummy_head.next = ListNode(val, self.dummy_head.next)
        node = ListNode(val,self.dummy_head.next)
        self.dummy_head.next = node
        self.size += 1

    def addAtTail(self, val: int) -> None:
        node = ListNode(val)
        cur = self.dummy_head
        while cur.next != None:  # 循环结束时,cur指向最后一个节点
            cur = cur.next
        cur.next = node
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        node = ListNode(val)
        if index > self.size or index <0:
            return
        cur = self.dummy_head  # 要在某一个节点之前添加节点,那么必须要知道这个节点之前的节点
        for i in range(index): # 循环结束时cur指向下标为index的节点之前的一个节点
            cur = cur.next
        node.next = cur.next
        cur.next = node
        self.size += 1

    def deleteAtIndex(self, index: int) -> None:
        if index >= self.size or index <0:
            return
        cur = self.dummy_head
        for i in range(index):
            cur = cur.next
        cur.next = cur.next.next  # cur指向的节点即cur.next,重新指向cur.next.next
        self.size -= 1

4.206. 反转链表

4.1题目及讲解

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

题目链接:https://leetcode.cn/problems/reverse-linked-list/description/
视频讲解:https://www.bilibili.com/video/BV1nB4y1i7eL/?spm_id_from=333.788&vd_source=d49b1b867faa78fdf891abde70b7422f
文字讲解:https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html

4.2代码实现

方法一:双指针

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        pre = None
        cur = head
        while cur:
            tmp = cur.next # 临时浮标
            cur.next= pre  #翻转
            pre = cur #pre后移
            cur = tmp #cur后移
        return pre

方法二:递归

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        return self.reverse(head, None)

    def reverse(self, cur: ListNode, pre: ListNode) -> ListNode:
        if cur ==None:
            return pre
        tmp = cur.next
        cur.next = pre  # 翻转
        return self.reverse(tmp,cur)

总结:
对链表的基础理论熟悉了,能够理解讲解的方法,但是代码实现还是不熟练,没办法独立写出来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值