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

文章目录

  • 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_node
        return
    last_node = self.head  # 遍历到链表的尾部
    while last_node.next:
        last_node = last_node.next
    last_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:  # 若链表为空,直接返回
        return
    if self.head.next is None:  # 若链表只有一个元素,将头节点设置为空
        self.head = None
        return
    second_to_last = self.head  # 找到倒数第二个节点
    while second_to_last.next.next:
        second_to_last = second_to_last.next
    second_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:  # 若找到目标数据,返回True
            return True
        current_node = current_node.next  # 移动到下一个节点
    return False  # 遍历完链表后,未找到目标数据,返回False

LinkedList.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 = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        if headA is None or headB is None:
            return

        pA, pB = headA, headB

        while pA != pB:
            pA = headB if pA is None else pA.next
            pB = headA if pB is None else pB.next

        return 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, head
        while cur:
            next = cur.next
            cur.next = pre
            pre = cur
            cur = next
        return 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 = x
        self.next = None

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """

        slow, fast = head, head
        while fast is not None and fast.next is not None and slow != None:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                return True
        return 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 = None

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        slow, fast = head, head
        while True:
            if not (fast and fast.next): return
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                break

        first= head
        while first != slow:
            first, slow = first.next, slow.next
        
        return 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 list2
        if not list2: return list1

        if list1.val <= list2.val:
            list1.next = self.mergeTwoLists(list1.next, list2)
            return list1
        
        list2.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 = 0
        while 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.next
            if l1: l1 = l1.next
            if l2: l2 = l2.next
        return 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 = head
        while fast and n:
            fast = fast.next
            n -=1

        while fast:
            fast = fast.next
            slow = slow.next
        
        slow.next = slow.next.next
        return 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,p
        while b.next and b.next.next:
            a,b = a.next,b.next.next
            tmp.next,a.next,b.next = b,b.next,a
            tmp,b = a,a
        return p.next

5. 参考文档

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nacos-默认token.secret.key-配置不当权限绕过漏洞复现

漏洞描述&#xff1a; Nacos 身份认证绕过漏洞(QVD-2023-6271)&#xff0c;开源服务管理平台 Nacos在默认配置下未对 token.secret.key 进行修改&#xff0c;导致远程攻击者可以绕过密钥认证进入后台&#xff0c;造成系统受控等后果。 漏洞信息 公开时间&#xff1a;2023-03…

Windows安装MongoDB结合内网穿透轻松实现公网访问本地数据库

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Java 基于微信小程序的校园失物招领小程序,附源码

博主介绍&#xff1a;✌程序员徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Java基础第十一课——类与对象(2)

由于类与对象这一部分的知识点很多&#xff0c;而且操作方法也有很多&#xff0c;所以这次将继续深入讨论一下关于类与对象中方法传参、方法重载、构造方法以及this关键字使用方面的知识。 一、方法传参 1.return关键字 return关键字作用 作用场景&#xff1a;方法内 作用…

一站式开源持续测试平台 MerterSphere 之测试跟踪操作详解

一、MeterSphere平台介绍 MeterSphere是一站式的开源持续测试平台&#xff0c;遵循 GPL v3 开源许可协议&#xff0c;涵盖测试跟踪、接口测试、UI 测试和性能测试等功能&#xff0c;全面兼容JMeter、Selenium 等主流开源标准&#xff0c;有效助力开发和测试团队充分利用云弹性…

NCF代码运行

keras 2.1.4 tensorflow 1.12.0 python 3.6.4 numpy 1.14.5 一、准备工作 1、安装虚拟环境 conda create -n tensorflow python3.6.4conda activate tensorflowconda install tensorflow1.12.0conda install keras2.1.4conda info2、安装相应依赖 cd Py3_Recommender-Syste…

4.2 面向对象程序设计-类的继承实验

本文仅供学习交流&#xff0c;严禁用于商业用途&#xff0c;如本文涉及侵权请及时联系将于24小时内删除 目录 1.实验内容 2.实验原理 2.1类的继承 2.2 继承的优点和缺点 2.3 继承的方式 3.实验代码 1.实验内容 创建一个父类CalcTime&#xff0c;在父类中依次定义用于保存…

对装饰器模式的理解

目录 一、场景二、面对场景中的新需求&#xff0c;我们怎么办&#xff1f;1、暴力法&#xff1a;直接修改原有的代码。2、子类继承法&#xff1a;既然要增强行为&#xff0c;那我搞一个子类&#xff0c;覆写不就完事了&#xff1f;3、装饰器模式 三、对装饰器模式的思考1、从代…

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

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

Shopee(虾皮)有哪些站点?

虾皮&#xff08;Shopee&#xff09;是东南亚地区的跨境平台&#xff0c;目前拥有多个站点&#xff0c;以下是对虾皮各站点的简要介绍&#xff1a; 中国台湾站&#xff1a;作为大多数新卖家的默认首站&#xff0c;台湾站没有语言障碍&#xff0c;运营起来更为方便&#xff0c;…

Java 中文官方教程 2022 版(一)

原文&#xff1a;docs.oracle.com/javase/tutorial/reallybigindex.html 教程&#xff1a;入门指南 原文&#xff1a;docs.oracle.com/javase/tutorial/getStarted/index.html 这个教程提供了关于开始使用 Java 编程语言的所有必要信息。 提供了 Java 技术作为一个整体的概述。…

android gradle版本无法下载

android gradle版本无法下载问题解决方法 在引入一个新的android项目的时候&#xff0c;通常会因为无法下载gradle版本而一直卡在同步界面&#xff0c;类似于下面的情况。 这是因为gradle运行时首先会检查distributionUrlhttps://services.gradle.org/distributions/gradle-5.6…

Springboot+Vue项目-基于Java+MySQL的社区团购系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

【linux篇】ubuntu安装教程

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

ControllerAdvice用法

ControllerAdvice用法 ControllerAdvice是一个组件注解&#xff0c;它允许你在一个地方处理整个应用程序控制器的异常、绑定数据和预处理请求。这意味着你不需要在每个控制器中重复相同的异常处理代码&#xff0c;从而使得代码更加简洁、易于管理。 主要特性 全局异常处理&a…

AI绘梦师新项目歪门邪道2.0游戏玩法,仅需拷贝,一键生成,单日盈利500

我们今天要介绍的项目是“AI绘梦师新项目歪门邪道2.0游戏玩法”。这个项目的核心是利用AI技术帮助企业将用户的梦境转化为美术作品。操作起来非常简单&#xff0c;只需复制用户描述的梦境内容&#xff0c;然后将其输入到AI绘画软件中&#xff0c;软件就能自动生成相应的画作。 …

mysql索引与优化问题

作为一个java程序员&#xff0c;mysql数据库面试应该是比较多的了&#xff1b;而关于数据库的面试&#xff0c;最多的就是性能问题&#xff0c;而以性能为起点&#xff0c;延伸出很多具体的问题。 我们使用第一性原理的方法来分析&#xff0c;为什么面试中一定会问数据库的索引…

俄罗斯人遇到智障都怎么表达,柯桥成人俄语学习日常口语教学

你知道俄罗斯人 口吐芬芳 表达友好时怎样称呼他人吗&#xff1f; “兔崽子”“蠢货”“白痴”......你知道这些词用俄语都怎样说吗&#xff1f; 事先声明&#xff1a;本期不正经科普仅供娱乐&#xff0c;实操之后挨打了不要怪小编哦~ 1、тетеря 笨蛋 <转, 俗, 谑&g…

dfs板子

递归实现排列 留着明早省赛之前看 #include<iostream> using namespace std; int arr[10010]; int brr[10010]; int n,k; void dfs(int num){if(num > n){for(int i 1;i < n;i){cout << arr[i] << " ";}cout << endl;return;}for(in…

210. 课程表 II

题目重现: 方法一: 根据拓扑排序的人工模拟推导的算法 基本思想就是统计每个节点的入度 入度为0进入队列 在循环中每次 从队列中移出一个元素 并把它指向的元素入度减一 同样的入度为0进入队列 当队列为空 或者 次数达到numCourse 退出循环 class Solution { public:v…