北大硕士LeetCode算法专题课--链表相关问题

news2025/1/20 1:44:38

算法面试相关专题:

北大硕士LeetCode算法专题课-字符串相关问题_

北大硕士LeetCode算法专题课-数组相关问题_

北大硕士LeetCode算法专题课-基础算法查找_

北大硕士LeetCode算法专题课-基础算法之排序_

北大硕士LeetCode算法专题课---算法复杂度介绍_

北大硕士LeetCode算法专题课-查找相关问题_

链表的概

链表Linked list是一种常见的基础数据结,是由一组不必相连【不必相连:可以连续也可以不连续】的内存结构 【节点】,  按特定的顺序链接在一起的抽象数据类型。

链表中的元素称为节点(node),每一个节点都有两个属性

一个用来记录当前节点中保存的数据

一个用来记录下一个节点的引用

链表是节点的集合。第一个节点(Node)一般被称为Head。最后一个节点的Next属性必须指向 None ,表明是链表的结尾

 链表和数组的区

在大多数编程语言中,链表和数组在内存中的存储方式存在明显差异。数组要求内存空间是连续的,链表可以不连续。 然而,在 Python list是动态数组。所以在Python中列表和链表的内存使用非常相似。

链表和数组在以下的操作中也有本质区别:

插入元素:数组中插入元素时,插入位置之后的所有元素都需要往后移动一位,所以数组中插入元素最坏时间复杂度是 O(n)链表可以达到 O(1) 的时间复杂度

删除元素:数组需要将删除位置之后的元素全部往前移动一位,最坏时间复杂度是 O(n)链表可以达到 O(1) 的时间复杂度

随机访问元素:数组可以通过下标直接访问元素,时间复杂度为O(1)。链表需要从头结点开始遍历,时间复杂度为O(n)

获取长度: 数组获取长度的时间复杂度为O(1),链表获取长度也只能从头开始遍历,时间复杂度为O(n)

实现链

先创建一个类,LinkedList

class LinkedList:
def 	init 	(self):
self.head = None

 LinkedList中,需要存储的唯一信息是链表的开始位置(链表的头部)。接下来,创建另一个类Node来表示链表的 每个节点

class Node:
def 	init 	(self, data):  self.data = data  self.next = None

我们可以给刚创建的两个类添加   repr   方法, 在创建实例的时候输出更多有用的信息

class LinkedList:
def 	init 	(self):
self.head = None

def 	repr 	(self):  node = self.head  nodes = []
while node is not None:  nodes.append(node.data)  node = node.next
nodes.append("None")
return " -> ".join(nodes)
class Node:
def 	init 	(self, data):  self.data = data  self.next = None

def 	repr 	(self):
return self.data

创建测试类, 测试上面的代码

from LinkedList import LinkedList
from Node import Node

if  		name 	 == ' 	main 	':  llist = LinkedList()  print(llist)

first_node = Node('a')  llist.head = first_node  print(llist)

second_node = Node('b')  third_node = Node('c')  first_node.next = second_node  second_node.next = third_node  print(llist)

 

修改   init   方法,可以传入列表快速创建LinkedList

def 	init 	(self, nodes=None):
self.head = None
if nodes is not None:
node = Node(data=nodes.pop(0))
self.head = node
for elem in nodes:
node.next = Node(data=elem)  node = node.next

 实现链表,添加节点

在头部添加Node:在链表的开头添加一个Node,不必遍历链表,只需将新的Nodenext属性指向 self.head ,  并将新的node设置为新的 self.head

 在尾部添加Node:必须遍历链表,与list不同list可以直接获取长度, 链表只有从第一个Node,不断的去获取下一个Node  才能知道链表的尾部

def add_last(self, node):
if self.head is None:  self.head = node  return
for current_node in self:  pass
current_node.next = node

在指定元素后添加Node:遍历链表找到目标Node 把目标Node的下一个元素, 赋值给要添加Nodenext属性, 然后修改 目标Nodenext属性, 指向新添加的Node, 当链表为空以及目标元素不存在时抛出异常

def add_after(self, target_node_data, new_node):
if self.head is None:
raise Exception("List is empty")

for node in self:
if node.data == target_node_data:  new_node.next = node.next  node.next = new_node
return

raise Exception("Node with data '%s' not found" % target_node_data)

在指定元素前添加Node:遍历链表找到目标Node,还需要记录当前节点的前一个节点。

def add_before(self, target_node_data, new_node):
if self.head is None:
raise Exception("List is empty")

if self.head.data == target_node_data:
return self.add_first(new_node)

prev_node = self.head  for node in self:
if node.data == target_node_data:  prev_node.next = new_node  new_node.next = node
return
prev_node = node

raise Exception("Node with data '%s' not found" % target_node_data)

实现链表,删除节

删除Node:遍历链表找到目标Node,将目标Node的前一个Nodenext属性,指向目标Nodenext节点

def remove_node(self, target_node_data):
if self.head is None:
raise Exception("List is empty")

if self.head.data == target_node_data:
self.head = self.head.next  return

previous_node = self.head  for node in self:
if node.data == target_node_data:  previous_node.next = node.next  return
previous_node = node

raise Exception("Node with data '%s' not found" % target_node_data)

其它常见链表介

刚才实现的是单链表,常见链表除了单链表之外还有双向链表以及循环链表

双向链表,顾名思义,Node中除了记录下一个元素next之外, 还通过一个属性记录上一个元素

刚才实现的是单链表,常见链表除了单链表之外还有双向链表以及循环链表

循环链表,将单链表中最后一个Nodenext 属性, 指向头节点(head),即为循环链表

反转链表(LeetCode 206)

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

示例:

 

 

移除链表元素(LeetCode 203

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

示例1:

由于链表的头节点 head 有可能需要被删除,因此创建哑节点 dummyHead dummyHead.next=head初始化 temp=dummyHead然后遍历链表进行删除操作。最终返回 dummyHead.next即为删除操作后的头节点。

def removeElements(head, val):  dummy_head = Node(0)  dummy_head.next = head  temp = dummy_head
while temp.next:
if temp.next.data == val:  temp.next = temp.next.next
else:
temp = temp.next
return dummy_head.next

复杂度分析 时间复杂度:O(n),其中 n 是链表的长度。需要遍历链表一次。 空间复杂度:O(1)

两两交换链表中的节点(LeetCode 24)

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本 题(即,只能进行节点交换)。

示例 1:

 

 

删除链表中的节点(LeetCode 237)

给请编写一个函数,用于 删除单链表中某个特定节点 。在设计函数时需要注意,你无法访问链表的头节点 head ,只 能直接访问 要被删除的节点

题目数据保证需要删除的节点 不是末尾节点

 删除链表中的节点(LeetCode 237)

思路分析:我们在做链表元素删除时, 一般的思路是,

找到要删除节点的上一个节点

将上一个节点的next属性 指向要删除节点的下一个节

 但是,当前题目中的要求是, 我们无法访问头结点, 那么我们就无法得知要删除节点的上一个节点,但是我们能够获 取要删除节点的下一个节点, 利用它来完成我们的需求

[4, 5,1, 9] 链表,删除节点 5。既然要删除5 我们把5的下一个节点的值付给它,然后删除下一个节点

删除链表中的倒数第N个节点(LeetCode 19)

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

输入:head = [1,2,3,4,5], n = 2

输出:[1,2,3,5]

删除链表中的倒数第N个节点(LeetCode 19)

思路: 首先遍历获取长度,创建一个虚拟头结点,从虚拟头结点开始遍历, Ln+1 个节点。当遍历到第 Ln+1个节 点时,它的下一个节点就是我们需要删除的节点

def removeNthFromEnd(head, n):
def getLength(head):  length = 0
while head:
length += 1
head = head.next
return length

dummy = Node(0)  dummy.next = head
length = getLength(head)  cur = dummy
for i in range(1, length - n + 1):  cur = cur.next
cur.next = cur.next.next
return dummy.next

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/155235.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

荧光定量PCR检测法的原理和应用领域

一、荧光定量PCR原理 在PCR扩增反应体系中加入荧光基团就是荧光定量PCR(Real-time PCR),通过对扩增反应中每一个循环产物荧光信号的实时检测,最后通过标准曲线对未知模板进行定量分析的方法。 以探针法荧光定量PCR为例:PCR扩增时…

STM32G0开发笔记-Platformio+libopencm3-EEPROM M24C02使用

使用Platformio平台的libopencm3开发框架来开发STM32G0,以下为EEPROM M24C02的使用方法。 1 新建项目 建立eeprom项目 在PIO的Home页面新建项目,项目名称eeprom,选择开发板为 MonkeyPi_STM32_G070RB,开发框架选择libopencm3&am…

loss盘点: GIoU loss (拆 PaddleDetection 轮子)

1. GIoU 计算 关于 GIoU 的实现,可直接参看原文给出的网站: https://giou.stanford.edu/ GIoU∣A∩B∣∣A∪B∣−∣C∖(A∪B)∣∣C∣IoU−∣C∖(A∪B)∣∣C∣GIoU \frac { |A \ \cap \ B | } { |A \ \cup \ B | } - \frac { | C \setminus (A \ \cup \…

Spring MVC 总结

Spring MVC Spring MVC 是 javaWeb 的开发模块,是一个架构模式,是整个 javaWeb 开发领域 最重要的一个技术。 Spring MVC 文档 Spring MVC 是 Spring 体系的 轻量级Web MVC框架。Spring MVC 的核心 Controller 控制器,用于处理请求&#xff…

C语言入门(五)——深入理解函数

return 语句 增量式开发 递归 return 语句 之前我们一直在main函数中使用return语句,现在是时候全面深入地学习一下。在有返回值地函数中,return语句的作用是提供整个函数的返回值,并结束当前函数返回到调用它的地方。在没有返回值的函数中…

vue修改el-input样式,样式穿透

vue–element的form表单中修改el-input样式 在使用 element ui 组件过程中,我最近碰到了新的问题。 初始的界面效果是这样的: 这个效果真的不怎么好看,我想把输入框的背景色变浅,变得透明。于是我在代码中添加 .el-input{backgro…

Polygon生态

1. 引言 当前区块链存在不可能三角问题: 1)去中心化2)可扩展性3)安全性 当前单一链仅能兼顾不可能三角中的2个维度,而无法做到三者兼顾。 区块链中的主要角色有: 1)共识层——负责对包含在…

python基础篇之数字类型(上)

大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页:lqj_本人的博客_CSDN博客-微信小程序,前端,vue领域博主lqj_本人擅长微信小程序,前端,vue,等方面的知识https://blog.csdn.net/lbcyllqj?spm1000.2115.3001.5343 哔哩哔哩欢迎关注&…

【NI Multisim 14.0原理图设计基础——元器件属性设置】

目录 序言 一、属性编辑 二、元器件属性设置 🍉 1.“标签”选项卡 🍉2.“显示”选项卡 🍉 3.“值”选项卡 🍉 4.“故障”选项卡 🍉5.“管脚”选项卡 🍉 6.“变体”选项卡 🍉 7.“用户字…

正则表达式查漏补缺(包括es9的新方法)

一、创建正则 1、方法创建正则 // let regnew RegExp("a","ig")//检查字符串中是否包含a // let str"a" // console.log(reg.test("As"))i是忽略大小写 g是全局匹配,不会只返回一个 2、字面量创建正则 // let reg/a|c/…

挂载本地光盘

一、挂载本地光盘到/mnt 使用mount模块 二.配置YUM源 (1)使用yum_repository模块 (2) 控制端主机编辑配置文件使用synchronize模块发送到受控主机 (3) 使用file模块创建一个base.repo文件,并…

HarmonyOS鸿蒙学习笔记(17)获取屏幕宽高等属性

ohos.display组件使用获取屏幕属性的三种方法getDefaultDisplay(callback: AsyncCallback<Display>)的用法getDefaultDisplay()的用法getAllDisplay(callback: AsyncCallback<Array<Display>>)的用法参考资料ohos.display屏幕属性提供管理显示设备的一些基础…

linux 设备树简析

1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. 设备树的来源 在 Linux 中&#xff0c;每个设备驱动&#xff0c;管理一组设备数据&#xff0c;类似面向对象编程中类和其实例对象的关系。一段时…

VMware-【Linux】centos7 /boot磁盘扩容

我的/boot当时安装的时候只分了不到200MB现在不够了所以扩容下这是我学习的文章&#xff0c;细节说明了很多地方还有一些坑&#xff1a;https://blog.51cto.com/u_15801765/5697187开始操作前&#xff0c;可以先用命令 df -hl 记录一下你现在/boot 剩余磁盘空间。到文章最后面我…

设计模式_创建型模式 -《工厂模式》

设计模式_创建型模式 -《工厂模式》 笔记整理自 黑马程序员Java设计模式详解&#xff0c; 23种Java设计模式&#xff08;图解框架源码分析实战&#xff09; 概述 需求&#xff1a;设计一个咖啡店点餐系统。 设计一个咖啡类&#xff08;Coffee&#xff09;&#xff0c;并定义其…

MySQL学习之一条SQL查询语句的执行

文章目录前言一、MySQL基础架构二、连接器三、查询缓存四、分析器五、优化器六、执行器前言 今天我们通过一条SQL查询语句的执行过程&#xff0c;来剖析MySQL的基础架构。让我们从宏观上先有一个对MySQL的认识与了解 一、MySQL基础架构 首先&#xff0c;我们要对MySQL的整体架…

深入分析Linux PCI驱动框架分析(二)

说明&#xff1a; Kernel版本&#xff1a;4.14ARM64处理器使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 概述 本文将分析Linux PCI子系统的框架&#xff0c;主要围绕Linux PCI子系统的初始化以及枚举过程分析&#xff1b;如果对具体的硬件缺乏了解&#xff…

详解c++---vector介绍

这里写目录标题什么是vectorvector的定义reservevector数据插入push_backinsertresizeassignvector数据的删除pop_backeraseclearvector性质查看sizecapacityemptymax_sizevector元素修改operator[ ]atfrontbackvector其他函数operatorswap什么是vector vector是表示可变大小数…

深入浅出Cookie、Session、Token:背后的技术原理

目录 简介 . 网站交互体验升级 1.1 无状态的 HTTP 协议 1.2 解决之道 2. Cookie方案 2.1 Cookie 定义和作用 2.2 服务端创建 Cookie 2.4 存在的问题 3. Session 方案 3.1 Session 机制的概念 3.2 简单的交互流程 3.3 Session 的实现方式 3.4 存在的问题 4. Token…

【微服务】Nacos 认证机制

目录 一、背景 二、需求 三、方案 1、安全架构选型 2、会话管理 2.1、会话选型 2.2、Session 登录流程 2.3、Token 登录流程 2.4、jwt 框架选型 2.5、会话超时 3、SSO 支持 4、UI设计 5、接口设计 6、数据库表设计 6.1、user表 6.2、roles表 7、Filter 拦截请求…