大家好呀,我是蛋蛋。

今天来设计链表,强行学明白链表的 5 种操作。

板凳摆好,直接开整。

LeetCode 107:设计链表

题意

实现链表的查找、头插法、尾插法、通用插入、删除操作:

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

示例

提示

  • 1 <= val <= 1000
  • 1 <= 操作次数 <= 1000
  • 不能使用内置的 LinkedList 库

题目解析

水题,难度中等,考察链表的常规操作。

如果对链表还不太熟悉,请看下面这篇文章:

ACM 选手带你玩转链表!

仔细来看,这道题主要涉及 5 种操作:

  • 查找链表第 index 个节点的值
  • 在链表的第一个节点前插入一个节点
  • 在链表的最后一个节点后插入一个节点
  • 在链表的第 index 节点前插入一个节点
  • 删除链表的第 index 个节点。

这 5 种包含了链表的常见增删查操作,是刚学完链表的臭宝们及时巩固知识的绝佳练习题。

这道题我用带头节点的单链表来实现。

头节点,可能很多人叫做哨兵节点,放在第一个元素的节点之前,数据域一般没意义。

图解

链表题呢,为了方便后续的操作,一般上来先定义一个简单的节点类:

# 自定义单节点
class Node:def __init__(self, data):self.val = dataself.next = None

链表类里初始化头节点和链表长度。

def __init__(self):"""Initialize your data structure here."""# 头节点self.head = Node(0)# 保存链表长度self.length = 0

get(index) ,查找节点,没啥好说的,就是傻傻的从第 1 个节点开始找。时间复杂度 O(n)。

addAtHead(val) ,在链表第一个节点前插入一个节点,很好插,找到第一个节点的前驱节点就好,在这就是头节点。

因为就在第 1 个,所以时间复杂度 O(1)。

**链表插入一定切记:插入操作的顺序不能改变!**切记!

一定是待插入节点的后继指针先指,然后前驱节点再指向待插入节点。

在下图对应的是值为 10 的节点先指向值为 11 的节点,然后值为 0 的头节点再指向值为 10 的节点。

同理,addAtTail(val) 在链表最后一个节点后插入节点,也很简单,要插入的节点位置的前驱节点就是最后一个节点。

因为在最后一个,时间复杂度 O(n)。

addAtIndex(index, val),在链表的第 index 节点前插入一个节点,其实这个就是插入的通用操作。

同样从第一个节点开始依次查找,时间复杂度 O(n)。

addAtHead(val) 相当于 addAtIndex(0, val)。

addAtTail(val) 相当于 addAtIndex(length, val)。

deleteAtIndex(index),删除链表的第 index 个节点,同样是找到要删除节点的前驱节点,通过改变节点后继指针来删除。

同理,删除链表的时间复杂度也是 O(n)。

代码实现

Python 代码实现

# 自定义单节点
class Node:def __init__(self, data):self.val = dataself.next = Noneclass MyLinkedList:def __init__(self):"""Initialize your data structure here."""# 头节点self.head = Node(0)# 保存链表长度self.length = 0def get(self, index: int) -> int:"""Get the value of the index-th node in the linked list. If the index is invalid, return -1."""# 判断输入的索引是否有效if index < 0 or index >= self.length:return -1p = self.headi_index = 0# range 是左闭右开区间,相当于[0,index+1)for _ in range(index + 1):p = p.nextreturn p.valdef addAtHead(self, val: int) -> None:"""Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list."""return self.addAtIndex(0, val)def addAtTail(self, val: int) -> None:"""Append a node of value val to the last element of the linked list."""return self.addAtIndex(self.length, val)def addAtIndex(self, index: int, val: int) -> None:"""Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted."""# 特殊情况 index < 0 和 index = 0,则说明是头插法if index < 0:index = 0if index > self.length:returnp = self.headadd_node = Node(val)# 找到第 index 个节点的前驱节点for _ in range(index):p = p.nextadd_node.next = p.nextp.next = add_node# 插入节点,链表长度 +1self.length += 1def deleteAtIndex(self, index: int) -> None:"""Delete the index-th node in the linked list, if the index is valid."""# 判断输入的索引是否有效if index < 0 or index >=self.length:returnp = self.head# 找到要删除节点的前驱节点和要删除的节点for _ in range(index + 1):# 前驱节点pre = p# 要删除节点p = p.nextpre.next = p.next# 释放删除节点的内存p = None# 删除节点,链表长度 -1self.length -= 1# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)

好啦,图解设计链表到这就结束啦。

基础薄弱的臭宝好好思考下这道题,想明白了,就踏出学好链表的第一步啦。

看完的是真爱,点赞在看留言么么哒给本蛋起飞~

我是蛋蛋,我们下次见!

推荐阅读

【实战】ACM 选手图解 LeetCode 设计链表相关推荐

  1. leetcode设计链表,非常工整的实现你值得拥有

    设计链表的实现.您可以选择使用单链表或双链表.单链表中的节点应该具有两个属性:val 和 next.val 是当前节点的值,next 是指向下一个节点的指针/引用.如果要使用双向链表,则还需要一个属性 ...

  2. LeetCode刷题---707. 设计链表(双向链表-带头尾双结点)

    文章目录 一.编程题:707. 设计链表(双向链表-带头尾双结点) 1.题目描述 2.示例1: 3.提示: 二.解题思路 1.思路 2.复杂度分析: 3.算法图解(双向链表) 三.代码实现 三.单向链 ...

  3. LeetCode实战:合并K个排序链表

    题目英文 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexi ...

  4. 设计链表(Leetcode第707题)

    此题涵盖了链表的常见操作,是练习链表操作非常好的一道题目 此题涵盖了链表的常见操作,是练习链表操作非常好的一道题目 此题涵盖了链表的常见操作,是练习链表操作非常好的一道题目 题目描述: 设计链表的实现 ...

  5. 【手绘漫画】图解LeetCode之旋转链表(LeetCode 61题)

    文章目录 图解LeetCode刷题计划 1.写在前面 2.题目 3.正文 4.代码 图解LeetCode刷题计划 1.写在前面 手绘漫画系列正式上线!!!"图解LeetCode刷题计划&qu ...

  6. 【手绘漫画】图解LeetCode之相交链表(LeetCode 160)

    文章目录 图解LeetCode刷题计划 1.写在前面 2.题目 3.正文 4.代码 图解LeetCode刷题计划 1.写在前面 手绘漫画系列正式上线!!!"图解LeetCode刷题计划&qu ...

  7. 【手绘漫画】图解LeetCode之两两交换链表中的节点(LeetCode 24)

    文章目录 图解LeetCode刷题计划 1.写在前面 2.题目 3.正文 4.代码 图解LeetCode刷题计划 1.写在前面 手绘漫画系列正式上线!!!"图解LeetCode刷题计划&qu ...

  8. 卷进大厂系列之LeetCode刷题笔记:设计链表(中等)

    学算法,刷力扣,加油卷,进大厂! 题目描述 力扣题目链接 设计链表的实现.您可以选择使用单链表或双链表.单链表中的节点应该具有两个属性:val 和 next.val 是当前节点的值,next 是指向下 ...

  9. leetcode 707 设计链表

    设计链表的实现.您可以选择使用单链表或双链表.单链表中的节点应该具有两个属性:val 和 next.val 是当前节点的值,next 是指向下一个节点的指针/引用.如果要使用双向链表,则还需要一个属性 ...

最新文章

  1. python基础常用语句-Python-基础-常用术语对照表
  2. Arduino编程之Serial.println()和Serial.print()
  3. Pandas常用I/O(一)------read_csv(),read_table()
  4. 混合云的承诺,收益和产品
  5. jquery将html转换word,HTML代码转word!亲测!可用!!!
  6. c#(.net)对dbf(arcgis shp属性表)的操作 (验证版)
  7. NachOS简述和源文件
  8. ROS,launch学习
  9. select下拉框带模糊查询_从零学会SQL:简单查询 -第二节
  10. Maven运行时异常java.lang.UnsupportedClassVersionError的解决方案
  11. 数字调制中比特率和波特率的关系
  12. 网络操作系统和分布式系统区别简介
  13. 解决Please define the NDK_PROJECT_PATH variable to point to it.
  14. 武汉市政府官网转载,长江日报、武汉电视台重磅报道,这场区块链大会厉害了!...
  15. JavaScript--ES6【Promise】对象详解
  16. php 路由器设置密码,为防蹭网宽带密码修改之后无线路由器设置教程
  17. N刷《我要投资》后,我发现了“成功人士”的秘诀
  18. java实现FTP协议:wireshark抓包解析
  19. 重点人员数据分析管控平台建设,重点人员系统开发
  20. linux系统怎么退出文本模式,linux的有关重启,文本模式的切换

热门文章

  1. 6-10漏洞利用-Smtp实验环境搭建
  2. 机器人最新天赋符文天赋加点图_《LOL》S10赛季机器人天赋符文加点出装攻略 这套方案胜率高达52.00%...
  3. 计算机技术专硕取消,专硕取消全日制,非全日制专硕变为未来趋势
  4. QQ 非绿钻如何上传本地歌曲 作为空间背景音乐
  5. LeetCode-Remove K Digits
  6. 数据结构(Java版 2022-10-30)
  7. 服务网格和Cookpad
  8. 登录页面显示不了验证码
  9. Android中打招呼
  10. The My Computer Software List