【leetcode刷题总结】——代码随想录(链表总结)

news2024/11/20 21:28:10

代码随想录按照数组-> 链表-> 哈希表->字符串->栈与队列->树->回溯->贪心->动态规划->图论->高级数据结构,再从简单刷起,做了几个类型题目之后,再慢慢做中等题目、困难题目。

以下是个人刷题总结,官方网站 https://programmercarl.com/

代码链接:Leetcode-Python: Leetcode-Python

目录

链表理论基础

203.移除链表元素

707.设计链表

206.反转链表

 24. 两两交换链表中的节点

19.删除链表的倒数第N个节点

160. 链表相交

142.环形链表II

总结


链表理论基础

什么是链表,链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

链表的入口节点称为链表的头结点也就是head。

单链表

数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。

链表是通过指针域的指针链接在内存中各个节点。

所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。

双链表

双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。

双链表 既可以向前查询也可以向后查询。

循环链表

循环链表,顾名思义,就是链表首尾相连。

循环链表可以用来解决约瑟夫环问题。

链表的定义

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

203.移除链表元素

力扣题目链接(opens new window)

题意:删除链表中等于给定值 val 的所有节点。

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

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

示例 3: 输入:head = [7,7,7,7], val = 7 输出:[]

这里添加虚拟节点的方法

class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        # 添加虚拟节点
        dummy_head = ListNode(next=head)
        cur = dummy_head
        while cur.next is not None:
            # 判断要删除的节点
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next
            return dummy_head.next

非常简单。最后要返回dummy_head.next。

707.设计链表

力扣题目链接(opens new window)

题意:

在链表类中实现这些功能:

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

这题有点长、可以进行拆分。

这道题目设计链表的五个接口:

  • 获取链表第index个节点的数值
  • 在链表的最前面插入一个节点
  • 在链表的最后面插入一个节点
  • 在链表第index个节点前面插入一个节点
  • 删除链表的第index个节点

可以说这五个接口,已经覆盖了链表的常见操作,是练习链表操作非常好的一道题目

class MyLinkedList(object):

    def __init__(self):
        self.head = Node()
        self.size = 0  # 设置一个链表长度的属性,便于后续操作,注意每次增和删的时候都要更新

    def get(self, index):
        """
        :type index: int
        :rtype: int
        """
        if index < 0 or index >= self.size:
            return -1
        cur = self.head.next
        while index:
            cur = cur.next
            index -= 1
        return cur.val

    def addAtHead(self, val):
        """
        :type val: int
        :rtype: None
        """
        # 新建新节点,将值置为val
        new_node = Node(val)
        # 头插法
        new_node.next = self.head.next
        self.head.next = new_node
        self.size += 1

    def addAtTail(self, val):
        """
        :type val: int
        :rtype: None
        """
        new_node = Node(val)
        cur = self.head
        # 只要链表的next不为空,遍历到最后的位置
        while cur.next:
            cur = cur.next
        # 在最后的位置插入元素 尾插法
        cur.next = new_node
        # 添加成功 链表长度+1
        self.size += 1

    def addAtIndex(self, index, val):
        """
        :type index: int
        :type val: int
        :rtype: None
        在指定位置添加链表元素
        """
        # 如果index<0 选择头插法
        if index < 0:
            self.addAtHead(val)
            return
        # 尾插法
        elif index == self.size:
            self.addAtTail(val)
            return
        # 不存在
        elif index > self.size:
            return

        node = Node(val)
        pre = self.head
        while index:
            pre = pre.next
            index -= 1
        node.next = pre.next
        pre.next = node
        self.size += 1

    def deleteAtIndex(self, index):
        """
        :type index: int
        :rtype: None
        """
        if index < 0 or index >= self.size:
            return
        pre = self.head
        while index:
            pre = pre.next
            index -= 1
        pre.next = pre.next.next
        self.size -= 1

206.反转链表

力扣题目链接(opens new window)

题意:反转一个单链表。

示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL

#思路

如果再定义一个新的链表,实现链表元素的反转,其实这是对内存空间的浪费

其实只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表,如图所示:

首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。

然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。

为什么要保存一下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了第一个节点了。

接下来,就是循环走如下代码逻辑了,继续移动pre和cur指针。

最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点。


# 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,最初是指向 null 的。
        pre = None
        # 第二个指针 cur 指向 head,然后不断遍历 cur
        cur = head
        # 每次迭代到 cur,都将 cur 的 next 指向 pre,然后 pre 和 cur 前进一位。
        while cur is not None:
            # 记录当前节点的下一个节点
            tmp = cur.next
            # 当前节点指向pre
            cur.next = pre
            # pre和cur节点都前进一位
            pre = cur
            cur = tmp
        return pre

 24. 两两交换链表中的节点

力扣题目链接(opens new window)

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head or not head.next:
            return head
        # 初始时,cur指向虚拟头结点
        newHead = head.next
        head.next = self.swapPairs(newHead.next)
        newHead.next = head
        return newHead

# 时间复杂度:O(n)
# 空间复杂度:O(1)

19.删除链表的倒数第N个节点

力扣题目链接(opens new window)

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

进阶:你能尝试使用一趟扫描实现吗?

class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        # 保存链表的长度
        len = 0
        cur = head
        while cur:  # 求链表的长度
            cur = cur.next
            len += 1

        # 添加虚拟节点
        dummy_head = ListNode(next=head)
        cur = dummy_head
        delect = 0
        while cur.next is not None:
            delect += 1
            # 判断要删除的节点
            if delect == len - n:
                cur.next = cur.next.next
            else:
                cur = cur.next
            return dummy_head.next


if __name__ == '__main__':
    sol = Solution()
    head = None
    for i in [4, 3, 2, 1, 0]:
        head = ListNode(i, head)
    t = 2
    print(sol.removeNthFromEnd(head, t))

160. 链表相交

力扣题目链接(opens new window)

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

# — coding: utf-8 –

# 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 not headA or not headB:
        #     return None
        # pa, pb = headA, headB
        # while pa != pb:
        #     if pa is None:
        #         pa = headB
        #     else:
        #         pa = pa.next
        #     if pb is None:
        #         pb = headA
        #     else:
        #         pb = pb.next
        # return pa

        # 我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置
        lenA, lenB = 0, 0
        cur = headA
        while cur:         # 求链表A的长度
            cur = cur.next
            lenA += 1
        cur = headB
        while cur:         # 求链表B的长度
            cur = cur.next
            lenB += 1
        # 搞俩个头
        curA, curB = headA, headB
        # 交换俩个头,让curB为最长链表的头,lenB为其长度
        if lenA > lenB:
            curA, curB = curB, curA
            lenA, lenB = lenB, lenA
        # 让curA和curB在同一起点上(末尾位置对齐)
        for _ in range(lenB - lenA):
            curB = curB.next
        #  遍历curA 和 curB,遇到相同则直接返回
        while curA:
            if curA == curB:
                return curA
            else:
                curA = curA.next
                curB = curB.next
        return None

142.环形链表II

力扣题目链接(opens new window)

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

为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。

 可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        slow, fast = head, head
        while fast and fast.next:
            # 慢指针一次移动一个,快指针一次移动两个
            slow = slow.next
            fast = fast.next.next
            # 相遇
            if slow == fast:
                index1 = head
                index2 = slow
                while index2 != index1:
                    index1 = index1.next
                    index2 = index2.next
                # 返回相交的指针
                return index1

总结

  • 链表的种类主要为:单链表,双链表,循环链表
  • 链表的存储方式:链表的节点在内存中是分散存储的,通过指针连在一起。
  • 链表是如何进行增删改查的。
  • 数组和链表在不同场景下的性能分析。

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

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

相关文章

多个Node.js版本之间切换

本篇文章会讲windows和Mac系统下实现多个node.js版本之间的切换。 1.windows下采用nvm&#xff08;nvm-window&#xff09; 2.Mac下采用nvm和n 注&#xff1a;window和mac下的nvm地址是不一样的 一、windows系统 什么是nvm&#xff1f; nvm是一个简单的bash脚本&#xff…

真题详解(有限自动机)-软件设计(七十七)

确定有限自动机 和 不确定有限自动机 解析&#xff1a; M1的A当0的时候&#xff0c;会变成A&#xff0c;也可能变成B&#xff0c; 所以M1是不确定有限自动机。 M2的A1的时候只会使A&#xff0c;0的时候只会是B B的0只会是B&#xff0c;1的时候只会是C。 C0的时候只会是B&a…

中小型企业需要“数据防泄露”吗?

数据防泄露是指企业采取的各种管理、技术与监督措施&#xff0c;以防止敏感和关键数据在传输、存储与使用过程中被未经授权访问或窃取&#xff0c;从而导致机密性、完整性或可用性受到损害。 数据防泄露工作通常包括数据分类与风险评估、权限管理与访问控制、加密与安全技术、数…

基于Gabor-小波滤波深度图表面法线的特征提取算法【通过正常Gabor-小波的直方图进行2D或3D特征提取】研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Bean的生命周期揭秘:从诞生到消亡,一个对象的壮丽演绎!

大家好&#xff0c;我是你们的小米。今天我要给大家揭秘一下Java开发中重要的概念——Spring Bean的生命周期。作为Java开发者&#xff0c;无论是在面试还是实际工作中&#xff0c;了解Bean的生命周期都是必备的知识点。让我们一起来深入了解吧&#xff01; 什么是Spring Bean …

【zabbix】PostgreSQL表信息查询收集监控

昨天开发那边给了一个需求&#xff0c;每隔一段时间查询一下数据库某表中的数据是否在最近更新&#xff0c;让我这边做一个监控信息收集 一、agent linux侧配置 这边目前就直接在zabbix上实现&#xff0c;首先就是脚本&#xff0c;我用python2实现 脚本名&#xff1a;check_y…

软件测试学什么——如何才能按时上线?

目录 引言 一、提前介入测试&#xff0c;认真做好需求分析。 二、测试计划没必要花太多精力。 三、测试用例编写 四、测试执行的关键点 五、测试环境 【一套系统提升学习的好资料】 阅读书籍文档 总结 引言 上线&#xff0c;永远是软件测试工程师最关注的问题。 上线…

Linux文件系统学习笔记

笔记 修改文件属性与权限数字修改文件权限符号修改文件权限 目录与文件的意义文件的权限目录的权限 路径 修改文件属性与权限 chgrp:修改用户组 chown:修改拥有者 chmod:修改用户权限 其中修改权限:chmod可以用数字修改或者符号修改 数字修改文件权限 一共有三种身份:拥有者…

freeswitch的2833和inband对接方案

概述 freeswitch支持三种模式的DTMF传输方式&#xff0c;分别时inband、INFO、2833。 在传统的PSTN网络中&#xff0c;所有的DTMF码都是inband模式&#xff0c;所以VOIP网络和PSTN网络对接中&#xff0c;需要将DTMF码做格式转换&#xff0c;通常是2833和inband之间的转换。 …

《思考致富》制造借口是一个根深蒂固的习惯

目录 经典摘录 领导方式有两种 拖拉 决心&#xff1a;克服拖拉的坏习惯&#xff08;通往致富之路的第七步&#xff09; 毅力&#xff1a;催生信念的持久努力&#xff08;通往致富之路的第八步&#xff09; 智囊团的力量&#xff1a;致富驱动力&#xff08;通往致富之路的第…

【分享】你用免费的GPT4了嘛?

哈喽&#xff0c;大家好&#xff0c;我是木易巷~ 现在OpenAI的ChatGPT4需要升级为plus会员使用&#xff0c;对于国内的用户来说&#xff0c;不仅需要魔法&#xff0c;还需要有一张外网的信用卡来开通会员&#xff0c;真的麻烦。 最近木易巷发现了一个项目&#xff0c;是GitHu…

基于欧式距离的聚类算法的Kmeans作业

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 基于欧式距离的聚类算法&#xff0c;其认为两个目标的距离越近&#xff0c;相似度越大。 该实验产生的点为二维空间中的点。 环境配置 java环境&#xff0c;使用原生的Java UI组件JPanel和JFrame 算法原理 基于欧式距离的聚…

问卷调查类型全面解析

调查问卷是从人们那里收集反馈和意见的强大工具。通过提出结构化问题&#xff0c;研究人员、组织和企业可以获得大量有关如何改进产品或服务、解决问题或做出明智决策的信息。但在设计调查问卷之前&#xff0c;必须首先了解不同的类型以及何时使用它们。 1、结构化问卷 结构化…

秀场、卖场、生态场,长沙为何连展会也与众不同?

文 | 智能相对论 作者 | 易不二 第三届长沙国际工程机械展览会已经完美落下帷幕。 依托长沙作为“工程机械之都”的硬核产业实力&#xff0c;又经过了多年耕耘&#xff0c;长沙国际工程机械展已经达到了跻身全球一流展会的水平。 4天的展期里&#xff0c;全球1502家企业参展…

【产品经理】产品体验报告准备

假如你已经决定为一个app写一份产品体验报告了&#xff0c;那么&#xff0c;我想说的是&#xff0c;不要急着动笔&#xff01; 下面就进入正题&#xff0c;在写产品体验报告之前&#xff0c;我会先去做哪些准备工作&#xff1a; &#xff08;1&#xff09;下载、把玩并熟悉app…

15-03 软件安全

系统安全 系统安全威胁 病毒蠕虫特洛伊木马Rootkit后门僵尸网络零日攻击Webshell 操作系统防御 杀毒软件&#xff1a;兵来将挡&#xff0c;水来土掩升级补丁&#xff1a;防止零日攻击限制&#xff1a;用户、网络、端口、程序、安全基准、不可变基础架构 杀毒软件检测机制 …

【猿人学WEB题目专解】猿人学第18题

&#x1f308;据说&#xff0c;看我文章时 关注、点赞、收藏 的 帅哥美女们 心情都会不自觉的好起来。 前言&#xff1a; &#x1f9e1;作者简介&#xff1a;大家好我是 user_from_future &#xff0c;意思是 “ 来自未来的用户 ” &#xff0c;寓意着未来的自己一定很棒~ ✨个…

财报解读 | 护肤业务乘风破浪,逸仙电商手握增长“王牌”

五年新战略计划进入第二年&#xff0c;逸仙电商能否如愿“一步、两步、三步”向前走&#xff1f; 5月16日&#xff0c;逸仙电商发布了2023年第一季度财报。财报显示&#xff0c;逸仙电商Q1实现营收8.91亿元&#xff0c;超出了此前指引上限&#xff1b;实现净利润5070万元&…

从0构建神经网络(1)从感知机到神经网络

一、前言 深度学习中有许多框架&#xff0c;包括Tensorflow、PyTorch、Keras等&#xff0c;框架中实现了各种网络&#xff0c;并且可以自动求导&#xff0c;因此构建一个完整的网络只需要十几行代码。因为框架高度封装&#xff0c;因此我们无法知道底层的原理。为了更好地理解…

【PCIE体系结构十一】部分物理层发送接收逻辑细节

&#x1f449;个人主页&#xff1a;highman110 &#x1f449;作者简介&#xff1a;一名硬件工程师&#xff0c;持续学习&#xff0c;不断记录&#xff0c;保持思考&#xff0c;输出干货内容 参考书籍&#xff1a;《PCI.EXPRESS系统体系结构标准教材 Mindshare》 目录 物理层…