链表中常见的使用方法逻辑整理

文章目录

  • 1. 链表特点
  • 2. 链表创建
  • 3. 链表遍历通用方法
    • 3.1 在链表的开头添加元素
    • 3.2 在链表的结尾添加元素
    • 3.3 删除链表的第一个元素
    • 3.4 删除链表的最后一个元素
    • 3.5 遍历链表
    • 3.6 查找链表中的元素
    • 3.7 反转链表
  • 4. 常见面试题
    • 4.1 相交链表
    • 4.2 反转链表
    • 4.3 环形链表
    • 4.4 环形链表 II
    • 4.5 合并两个有序链表
    • 4.6 两数相加
    • 4.7 删除链表的倒数第 N 个结点
    • 4.8 两两交换链表中的节点
  • 5. 参考文档

链表常见的使用方法逻辑整理


1. 链表特点

链表特点

  • 由节点组成:链表是由一个个节点组成的数据结构,每个节点包含数据和指向下一个节点的引用(指针/链接)。
  • 动态插入和删除:相对于数组,链表可以更轻松地进行节点的插入和删除操作,因为只需要调整节点的指针,而无需移动大量元素。
  • 内存利用灵活:链表的节点在内存中不必连续存储,这使得链表可以更灵活地利用内存,但也可能导致对内存的随机访问效率较低。
  • 随机访问效率低:链表的节点不能直接通过索引进行访问,需要从头节点开始逐个遍历,因此随机访问效率较低。
  • 多种类型:链表有单向链表、双向链表和循环链表等不同类型,每种类型都有不同的特点和适用场景。

链表是一种由节点组成的线性数据结构,每个节点包含一个数据元素和一个指向下一个节点的指针。跟数据对比有差异

  • 数组能够通过固定下标查找对应的数据,查找性能优越,但是每次插入/删除数据都需要将对应节点后续的数据整体挪移,因此数组的更新成本较大
  • 链表更新节点时只需要重新插入一个新节点,并调整上下节点的指针,无需移动后续的所有节点,因此更新成本较小,但是当需要获取当个节点数据时,由于没有固定下标,因此必须从头开始查找,因此查询性能较差

两者类型的数据结构,分别在读写时表现有差异,因此需要根据不同的应用场景(读写的频率差异)进行合理使用

2. 链表创建

链表中的每一个元素都是一个节点,每个节点通常包含两部分:数据和下一个节点的引用。

class Node:def __init__(self, data):self.data = data  # 节点存储的数据self.next = None  # 默认下一个节点为空class LinkedList:def __init__(self):self.head = None  # 初始链表为空

3. 链表遍历通用方法

3.1 在链表的开头添加元素

def add_first(self, data):new_node = Node(data)   # 创建新的节点new_node.next = self.head  # 将新节点指向当前的头节点self.head = new_node    # 更新头节点为新节点LinkedList.add_first = add_first

3.2 在链表的结尾添加元素

def add_last(self, data):new_node = Node(data)if self.head is None:  # 若链表为空,则直接将新节点设置为头节点self.head = new_nodereturnlast_node = self.head  # 遍历到链表的尾部while last_node.next:last_node = last_node.nextlast_node.next = new_node  # 在链表尾部添加新节点LinkedList.add_last = add_last

3.3 删除链表的第一个元素

def remove_first(self):if self.head:self.head = self.head.next  # 更新头节点为下一个节点LinkedList.remove_first = remove_first

3.4 删除链表的最后一个元素

def remove_last(self):if self.head is None:  # 若链表为空,直接返回returnif self.head.next is None:  # 若链表只有一个元素,将头节点设置为空self.head = Nonereturnsecond_to_last = self.head  # 找到倒数第二个节点while second_to_last.next.next:second_to_last = second_to_last.nextsecond_to_last.next = None  # 将倒数第二个节点的next设置为空,从而删除最后一个节点LinkedList.remove_last = remove_last

3.5 遍历链表

def print_list(self):current_node = self.head  # 从头节点开始遍历while current_node:print(current_node.data, end=" -> ")current_node = current_node.next  # 移动到下一个节点print("None")LinkedList.print_list = print_list

3.6 查找链表中的元素

def search(self, target):current_node = self.head  # 从头节点开始遍历while current_node:if current_node.data == target:  # 若找到目标数据,返回Truereturn Truecurrent_node = current_node.next  # 移动到下一个节点return False  # 遍历完链表后,未找到目标数据,返回FalseLinkedList.search = search

3.7 反转链表

def reverse(self):prev = None  # 上一个节点current = self.head  # 当前节点while current:next_node = current.next  # 记录下一个节点current.next = prev  # 将当前节点指向上一个节点prev = current  # 更新上一个节点为当前节点current = next_node  # 移动到下一个节点self.head = prev  # 更新头节点LinkedList.reverse = reverse

4. 常见面试题

一些总结

4.1 相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交:

在这里插入图片描述

题目数据 保证 整个链式结构中不存在环。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def getIntersectionNode(self, headA, headB):""":type head1, head1: ListNode:rtype: ListNode"""if headA is None or headB is None:returnpA, pB = headA, headBwhile pA != pB:pA = headB if pA is None else pA.nextpB = headA if pB is None else pB.nextreturn pA

4.2 反转链表

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

示例 1:
在这里插入图片描述

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例 2:

在这里插入图片描述

输入:head = [1,2]
输出:[2,1]
示例 3:

输入:head = []
输出:[]

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):def reverseList(self, head):""":type head: ListNode:rtype: ListNode"""pre, cur = None, headwhile cur:next = cur.nextcur.next = prepre = curcur = nextreturn pre 

4.3 环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例 1:

在这里插入图片描述

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

在这里插入图片描述

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

在这里插入图片描述

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

# Definition for singly-linked list.
class ListNode(object):def __init__(self, x):self.val = xself.next = Noneclass Solution(object):def hasCycle(self, head):""":type head: ListNode:rtype: bool"""slow, fast = head, headwhile fast is not None and fast.next is not None and slow != None:slow = slow.nextfast = fast.next.nextif slow == fast:return Truereturn False

4.4 环形链表 II

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

在这里插入图片描述

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

在这里插入图片描述

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

在这里插入图片描述

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def detectCycle(self, head):""":type head: ListNode:rtype: ListNode"""slow, fast = head, headwhile True:if not (fast and fast.next): returnslow = slow.nextfast = fast.next.nextif slow == fast:breakfirst= headwhile first != slow:first, slow = first.next, slow.nextreturn first

4.5 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:

在这里插入图片描述

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):def mergeTwoLists(self, list1, list2):""":type list1: Optional[ListNode]:type list2: Optional[ListNode]:rtype: Optional[ListNode]"""if not list1: return list2if not list2: return list1if list1.val <= list2.val:list1.next = self.mergeTwoLists(list1.next, list2)return list1list2.next = self.mergeTwoLists(list1, list2.next)return list2        

4.6 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:
在这里插入图片描述

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):def addTwoNumbers(self, l1, l2):""":type l1: ListNode:type l2: ListNode:rtype: ListNode"""cur = dummy = ListNode()carry = 0while l1 or l2 or carry:# 做加合运算carry += (l1.val if l1 else 0) + (l2.val if l2 else 0)# 如果超过10,需要做进位调整cur.next = ListNode(carry%10)#  取余数carry //= 10# 在一个节点cur = cur.nextif l1: l1 = l1.nextif l2: l2 = l2.nextreturn dummy.next

4.7 删除链表的倒数第 N 个结点

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

示例 1:

在这里插入图片描述

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

输入:head = [1], n = 1
输出:[]
示例 3:

输入:head = [1,2], n = 1
输出:[1]

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):def removeNthFromEnd(self, head, n):""":type head: ListNode:type n: int:rtype: ListNode"""slow = dummy_head = ListNode(next=head)fast = headwhile fast and n:fast = fast.nextn -=1while fast:fast = fast.nextslow = slow.nextslow.next = slow.next.nextreturn dummy_head.next

4.8 两两交换链表中的节点

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

示例 1:

在这里插入图片描述

输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:

输入:head = []
输出:[]
示例 3:

输入:head = [1]
输出:[1]

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):def swapPairs(self, head):""":type head: ListNode:rtype: ListNode"""p = ListNode(-1)a,b,p.next,tmp = p,p,head,pwhile b.next and b.next.next:a,b = a.next,b.next.nexttmp.next,a.next,b.next = b,b.next,atmp,b = a,areturn p.next

5. 参考文档

暂无,相关面试题请参考leetcode以及相关说明

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

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

相关文章

easyui combobox下拉框组件输入检索全模糊查询

前引&#xff1a; easyui下拉组件&#xff08;combobox&#xff09;&#xff0c;输入检索下拉内容&#xff0c;是默认的右模糊匹配&#xff0c;而且不支持选择。因业务要求需要做成全模糊查询&#xff0c;目前网上搜索有两种方案&#xff1a; 1.修改easyui源码&#xff0c;这个…

LeetCode700:二叉搜索树中的搜索

题目描述 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 null 。 代码 递归法 class Solution { public:TreeNode* searchBST(TreeN…

Visual Studio code无法正常执行Executing task: pnpm run docs:dev

最近尝试调试一个开源的项目&#xff0c;发现cmd可以正常启动&#xff0c;但是在vs中会报错&#xff0c;报错内容如下 Executing task: pnpm run docs:dev pnpm : 无法加载文件 E:\XXXX\pnpm.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 http…

组合导航的结果分段跳变问题

1 现象 用上海代数律动公司的AlgoT1-3组合导航设备采集数据进行组合导航算法调试&#xff0c;AlgoT1-3机器输出的结果很好很平滑&#xff0c;AlgoT1-3是带GNSS/INS的组合导航设备&#xff0c;另外还有一款更贵一点的带视觉的组合导航AlgoT1&#xff0c;效果会更好一些&#xf…

【Tars-go】腾讯微服务框架学习使用03-- TarsUp协议

3 TarsUP协议 统一通信协议 TarsTup | TarsDocs (tarscloud.github.io) TarsDocs/base at master TarsCloud/TarsDocs (github.com) &#xff1a; 有关于tars的所有介绍 每一个rpc调用双方都约定一套数据序列化协议&#xff0c;gprc用的是protobuff&#xff0c;tarsgo是统一…

每日OJ题_01背包③_力扣494. 目标和(dp+滚动数组优化)

目录 力扣494. 目标和 问题解析 解析代码 滚动数组优化代码 力扣494. 目标和 494. 目标和 难度 中等 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; …

ThreadX:怎么确定一个线程应该开多少内存

ThreadX&#xff1a;如何确定线程的大小 在实时操作系统&#xff08;RTOS&#xff09;ThreadX中&#xff0c;线程的大小是一个重要的参数。这个参数决定了线程的堆栈大小&#xff0c;也就是线程可以使用的内存空间。那么&#xff0c;我们应该如何确定一个线程需要多大的字节呢…

C语言-----结构体详解

前面已经向大家介绍过一点结构体的知识了&#xff0c;这次我们再来深度了解一下结构体。结构体是能够方便表示一个物体具有多种属性的一种结构。物体的属性可以转换为结构体中的变量。 1.结构体类型的声明 1.1 结构体的声明 struct tag {member-list;//结构体成员变量 }vari…

MySQL进阶二

目录 1.使用环境 2.排序窗口函数 3.聚合窗口函数 1.使用环境 数据库&#xff1a;MySQL 8.0.30 客户端&#xff1a;Navicat 15.0.12 接续MySQL进阶一&#xff1a; MySQL进阶一-CSDN博客文章浏览阅读452次&#xff0c;点赞9次&#xff0c;收藏4次。MySQL进阶操作一。https…

P4631 [APIO2018] 选圆圈

题目传送门https://www.luogu.com.cn/problem/P4631 代码传送门https://www.luogu.com.cn/record/155489748 本弱鸡抄的~

【linux篇】ubuntu安装教程

有道是工欲善其事必先利其器&#xff0c;在学习linux前&#xff0c;先得搭建好环境才能事半功倍。 1.VMware虚拟机安装 打开浏览器&#xff0c;可直接在搜索栏中输入VMware。

Docker+Uwsgi+Nginx部署Django项目保姆式教程

之前&#xff0c;我和大家分享了在docker中使用uwsgi部署django项目的教程。这次&#xff0c;为大家带来的是使用DockerUwsgiNginx部署Django项目。废话不多说&#xff0c;我们开干。 步骤1&#xff1a;使用命令创建一个django项目 我这里python版本使用的是3.9.x 首先&#…

什么场景适合使用Traefik?

Traefik 作为一款现代的反向代理和负载均衡器&#xff0c;已经成为云原生环境中的热门选择。它提供的动态配置能力和强大的自动化功能使其在多种场景中非常有用。本文将详细探讨适合使用 Traefik 的几种关键场景&#xff0c;并解释为何在这些情况下它特别有用 &#x1f30d;&am…

研发岗-面临统信UOS系统配置总结

第一步 获取root权限 配置环境等都需要用到root权限&#xff0c;所以我们先获取到root权限&#xff0c;方便下面的操作 下载软件 在UOS应用商店下载的所需应用 版本都比较低 安装node 官网下载了【arm64】的包&#xff0c;解压到指定文件夹&#xff0c;设置链接&#xff0…

2024年第十四届MathorCup数学应用挑战赛C题解析(更新中)

2024年第十四届MathorCup数学应用挑战赛C题解析&#xff08;更新中&#xff09; 题目题目解析(更新中&#xff09;问题一问题二问题三 题目 C题 物流网络分拣中心货量预测及人员排班电商物流网络在订单履约中由多个环节组成&#xff0c;图1是一个简化的物流 网络示意图。其中&a…

【心路历程】初次参加蓝桥杯实况

送给大家一句话&#xff1a; 寂静的光辉平铺的一刻&#xff0c;地上的每一个坎坷都被映照得灿烂。 – 史铁生 《我与地坛》 初次参加蓝桥杯有感 一点小小的震撼难评的做题过程A题 艺术与篮球问题描述解题 B 题 五子棋问题描述解题 C题 训练士兵问题描述解题 D题 团建解题 E题 …

Mogdb双网卡同步最佳实践

大家都知道Oracle数据库无论是单机还是RAC集群在进行生产部署实施时&#xff0c;我们都会对网卡做冗余考虑&#xff0c;比如使用双网卡&#xff0c;比如public、心跳网络。这样的目的主要是为了安全&#xff0c;避免淡点故障。当然也网卡Bond不仅是可以做主备还可以支持负载均衡…

IP地址定位技术在各领域的作用

IP地址定位是通过确定IP地址的物理位置来定位一个设备的技术&#xff0c;它在现代社会的多个领域中都有着广泛的应用。以下将详细探讨IP地址定位的应用场景&#xff0c;以期对读者有所启发。 首先&#xff0c;在网络安全领域&#xff0c;IP地址定位发挥着至关重要的作用。网络…

kali工具----网络映射器(Network Mapper)

识别活跃的主机 尝试渗透测试之前&#xff0c;必须先识别在这个目标网络内活跃的主机。在一个目标网络内&#xff0c;最简单的方法将是执行ping命令。当然&#xff0c;它可能被一个主机拒绝&#xff0c;也可能被接收。本节将介绍使用Nmap工具识别活跃的主机。 1、网络映射器工具…

深度学习的模型有几类,能干嘛用?

1、基础模型 &#xff08;1&#xff09;卷积神经网络 **卷积&#xff1a;**卷积的本质是通过矩阵运算9的方式将输入数据进行空间上的滤波&#xff0c;有效地提取数据中的局 部特征&#xff0c;从而实现特征数据更高程度的抽象表示。 **池化&#xff1a;**可以理解成“压缩”…