算法笔记-lc-707. 设计链表(中等)

Hifiasm参数调优实战:当N50不理想时的7个排查方向与解决方案 本文详细解析了Hifiasm参数调优实战,针对基因组组装中N50不理想的7个排查方向与解决方案。通过调整--hom-cov、-D、-N等核心参数,结合HiFi数据和参考基因组分析,有效提升组装质量。文章以猪毛菜基因组为例,展示了从2.1MB到4.3MB的N50优化过程,为生物信息学研究者提供实用指南。 阅读详情

题目

题干

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

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

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

示例:

MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3
linkedList.get(1); //返回2
linkedList.deleteAtIndex(1); //现在链表是1-> 3
linkedList.get(1); //返回3

提示:

所有val值都在 [1, 1000] 之内。
操作次数将在 [1, 1000] 之内。
请不要使用内置的 LinkedList 库。

解法

方法一:单向链表

思路

实现单向链表,即每个节点仅存储本身的值和后继节点。除此之外,我们还需要一个哨兵(sentinel)节点作为头节点,和一个size 参数保存有效节点数。如下图所示。
在这里插入图片描述

初始化时,只需创建头节点head 和 size 即可。

实现get(index) 时,先判断有效性,再通过循环来找到对应的节点的值。如下图所示。

在这里插入图片描述

实现addAtIndex(index, val) 时,如果 index 是有效值,则需要找到原来下标为 index 的节点的前驱节点 pred,并创建新节点to_add,将to_add 的后继节点设为 pred 的后继节点,将 pred 的后继节点更新为to_add,这样就将to_add 插入到了链表中。最后需要更新 size。这样的操作对于index=0 也成立,如以下两张图所示。
在这里插入图片描述
在这里插入图片描述

实现addAtHead(val) 和 addAtTail(val) 时,可以借助addAtIndex(index, val) 来实现。

实现deleteAtIndex(index),先判断参数有效性。然后找到下标为index 的节点的前驱节点 pred,通过将 pred 的后继节点更新为pred 的后继节点的后继节点,来达到删除节点的效果。同时也要更新size。如下图所示。

在这里插入图片描述

class MyLinkedList {
    int size;
    ListNode head;

    public MyLinkedList() {
        size = 0;
        head = new ListNode(0);
    }

    public int get(int index) {
        if (index < 0 || index >= size) {
            return -1;
        }
        ListNode cur = head;
        for (int i = 0; i <= index; i++) {
            cur = cur.next;
        }
        return cur.val;
    }

    public void addAtHead(int val) {
        addAtIndex(0, val);
    }

    public void addAtTail(int val) {
        addAtIndex(size, val);
    }

    public void addAtIndex(int index, int val) {
        if (index > size) {
            return;
        }
        index = Math.max(0, index);
        size++;
        ListNode pred = head;
        for (int i = 0; i < index; i++) {
            pred = pred.next;
        }
        ListNode toAdd = new ListNode(val);
        toAdd.next = pred.next;
        pred.next = toAdd;
    }

    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        size--;
        ListNode pred = head;
        for (int i = 0; i < index; i++) {
            pred = pred.next;
        }
        pred.next = pred.next.next;
    }
}

class ListNode {
    int val;
    ListNode next;

    public ListNode(int val) {
        this.val = val;
    }
}

复杂度分析

时间复杂度:初始化消耗 O(1),get 消耗 O(index),addAtHead 消耗 O(1),addAtTail 消耗 O(n),其中 n 为链表当前长度,即 addAtHead,addAtTail 和 addAtIndex 已调用次数之和,addAtIndex 消耗O(index)。

空间复杂度:所有函数的单次调用空间复杂度均为 O(1),总体空间复杂度为O(n),其中 n为 addAtHead,addAtTail 和 addAtIndex 调用次数之和。

方法二:双向链表

思路

实现双向链表,即每个节点要存储本身的值,后继节点和前驱节点。除此之外,需要一个哨兵节点作为头节点head 和一个哨兵节点作为尾节点tail。仍需要一个 size 参数保存有效节点数。如下图所示。
在这里插入图片描述

初始化时,只需创建头节点 head 和 size 即可。

实现 get(index) 时,先判断有效性,然后再比较从head 还是 tail 来遍历会比较快找到目标,然后进行遍历。如下图所示。

在这里插入图片描述

实现addAtIndex(index, val) 时,如果index 是有效值,则需要找到原来下标为 index 的节点 succ 和前驱节点 pred,并创建新节点to_add,再通过各自 prev 和next 变量的更新来增加to_add。最后需要更新 size。如以下两张图所示。

在这里插入图片描述

实现 addAtHead(val) 和addAtTail(val) 时,可以借助 addAtIndex(index, val) 来实现。

实现deleteAtIndex(index),先判断参数有效性。然后找到下标为index 的节点的前驱节点 pred 和后继节点 succ,再通过各自prev 和 next 变量的更新来删除节点,来达到删除节点的效果。同时也要更新size。如下图所示。

在这里插入图片描述

class MyLinkedList {
    int size;
    ListNode head;
    ListNode tail;

    public MyLinkedList() {
        size = 0;
        head = new ListNode(0);
        tail = new ListNode(0);
        head.next = tail;
        tail.prev = head;
    }

    public int get(int index) {
        if (index < 0 || index >= size) {
            return -1;
        }
        ListNode curr;
        if (index + 1 < size - index) {
            curr = head;
            for (int i = 0; i <= index; i++) {
                curr = curr.next;
            }
        } else {
            curr = tail;
            for (int i = 0; i < size - index; i++) {
                curr = curr.prev;
            }
        }
        return curr.val;
    }

    public void addAtHead(int val) {
        addAtIndex(0, val);
    }

    public void addAtTail(int val) {
        addAtIndex(size, val);
    }

    public void addAtIndex(int index, int val) {
        if (index > size) {
            return;
        }
        index = Math.max(0, index);
        ListNode pred, succ;
        if (index < size - index) {
            pred = head;
            for (int i = 0; i < index; i++) {
                pred = pred.next;
            }
            succ = pred.next;
        } else {
            succ = tail;
            for (int i = 0; i < size - index; i++) {
                succ = succ.prev;
            }
            pred = succ.prev;
        }
        size++;
        ListNode toAdd = new ListNode(val);
        toAdd.prev = pred;
        toAdd.next = succ;
        pred.next = toAdd;
        succ.prev = toAdd;
    }

    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        ListNode pred, succ;
        if (index < size - index) {
            pred = head;
            for (int i = 0; i < index; i++) {
                pred = pred.next;
            }
            succ = pred.next.next;
        } else {
            succ = tail;
            for (int i = 0; i < size - index - 1; i++) {
                succ = succ.prev;
            }
            pred = succ.prev.prev;
        }
        size--;
        pred.next = succ;
        succ.prev = pred;
    }
}

class ListNode {
    int val;
    ListNode next;
    ListNode prev;

    public ListNode(int val) {
        this.val = val;
    }
}

复杂度分析

时间复杂度:初始化消耗 O(1),get 消耗 O(index),addAtHead 消耗 O(1),addAtTail 消耗 O(1),addAtIndex 消耗O(index)。

空间复杂度:所有函数单次调用的空间复杂度均为 O(1),总体空间复杂度为 O(n),其中 n 为addAtHead,addAtTail 和 addAtIndex 调用次数之和。

电子工程师必看:dB与放大倍数快速换算表(附常见误区解析) 本文为电子工程师提供了dB与放大倍数快速换算的实战指南。文章深度解析了分贝的本质与核心价值,并提供了电压/电流与功率增益的速查表及心算技巧。重点剖析了混淆电压与功率dB、-3dB带宽理解等常见误区,并结合示波器、频谱仪测量及系统级应用,帮助工程师在实际工作中高效、准确地运用这一对数工具。 阅读详情

相关推荐

计算pi小数点后10000位

数据结构课上,老师让我们计算一下pi的10000位,复习一下面向对象。 First Try:定义一个高精度类hp(high precision),实现加减乘除,输入输出,然后随便找一个公式,比如Wallis公式,全都用hp进行计算。 现实是:大数乘大数或者大数除大数,实在是太慢了。而且Wallis公式收敛太慢。 Second Try先找到一个收敛较快的公司:BBP公式,观察公式发现,...

我的技术人生 7394

算法day03 | lc 203.移除链表元素 | lc 707.设计链表 | lc 206.反转链表

总结:今天进入新的数据结构,链表的学习,今天的题目本身并不难,但是需要特别细心,特别是在操作双链表的时候,一定要确定好代码的先后顺序,并使用临时变量保存后续要用到的数据。示例 1: 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL。// 链表变为 1->2->3。示例 3: 输入:head = [7,7,7,7], val = 7 输出:[]

qq_43008093的博客 2195

三维重建之条纹投影结构光(三)——相位展开优化与多频外差实践

本文深入探讨了三维重建中条纹投影结构光技术的核心环节——相位展开优化。针对传统路径跟踪法存在的误差传播与路径依赖问题,重点解析了多频外差法的原理与优势,并通过详细的C++代码实践,展示了如何利用三频外差法实现鲁棒、高精度的相位展开,从而获得连续的绝对相位图,为后续三维点云生成奠定坚实基础。

weixin_29074295的博客 529

代码随想录day03:链表 | 203.移除链表元素、707.设计链表、206.反转链表

最简单的想法. 其实就是新建一个链表, 然后将原链表的数据按照头插法插入进新的链表. (不过会造成空间资源的浪费)不过最优解是我们自己为其建立一个虚拟的头结点, 来优化链表的操作, 这样就不用对首元结点进行特殊的处理.那么如果按照一般思路来处理, 头结点是找不到前一个的, 所以需要对其进行特殊的处理.头结点如果需要移除, 那么将头结点更新为头结点的下一个.等于链表的长度,那么该节点会被追加到链表的末尾。, 作为检查的单位走下去, 移除需要的元素.的节点追加到链表中作为链表的最后一个元素。

2303_77648069的博客 1773

我的交叉验证翻车实录:从‘炼丹’到可靠评估,我是怎么用五折验证拯救我的图像分割模型的

本文分享了作者在医学图像分割模型评估中从失败到成功的实战经验。通过引入五折交叉验证方法,解决了传统数据划分的局限性,显著提升了模型评估的稳定性和泛化能力。文章详细介绍了Python实现、数据准备策略和训练流水线改造,为AI医疗影像分析提供了可靠的技术方案。

weixin_42625070的博客 269

Hypack 应用于地形测量的高级设置操作要领

Hypack 是业界公认最好的水文导航测量软件,是目前世界上应用广泛的专业测量疏浚软件。它能够接收,处理,存储和输出各种数据。Hypack支持绝大部分GPS,测深仪(国内如海鹰HY1603单波束测沙仪),多波束测深仪,旁扫声纳,涌浪补偿器,水位仪,验潮仪以及声速剖面仪。利用 Hypack 可以进行导航,单波束测量,多波束测量,旁扫测量以及疏浚实时监测等。软件界面友好,使用方便。本文简要阐述Hypack 应用于地形测量的几个重要操作要领。

中游鱼的博客 2793

二刷算法训练营Day03 | 链表(1/2) LC 203.移除链表元素 707.设计链表 206.反转链表

今日任务:链表理论基础 203.移除链表元素707.设计链表206.反转链表

记录学习每一天! 540

C++cgal库配置+VS2017

Cgal几何图形库在VS2017上的下载、安装与配置。想要一口气下载完所有安装配件的,可以去文章末尾的链接。httpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttps。

dsn3S的博客 1488

代码随想录算法训练营 Day3 | 链表 | LC.203、LC.206、LC.707

代码随想录算法训练营 Day3 | 链表 | LC.203、LC.206、LC.707

qq_48103649的博客 571

安卓手机部署酒馆 SillyTavern 全攻略(Termux 本地安装教程)

本文详细介绍了如何在安卓手机上通过 Termux 环境本地部署 SillyTavern,一个功能丰富的角色扮演对话 AI。步骤包括安装 Termux、Git,克隆 SillyTavern 仓库,安装 Node.js 和依赖,启动 SillyTavern,以及可选的高阶玩法——安装 TAI-Extras 扩展模块。文章还提供了常见问题的解决方案和优化技巧,如更新 SillyTavern、处理报错、文件访问、添加快捷命令和禁用安卓后台进程杀死。通过本教程,用户可以在安卓手机上体验本地部署的 AI 对话,享受更高

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1万+

SmartFusion从FPGA到ARM系列教程

前言 本系列教程,将会以Microsemi SmartFusion一代芯片A2F200M3F为例,简单介绍片上ARM Cortex-M3 硬核 MCU 基本外设的使用,及其与FPGA逻辑模块进行交互的示例。 在学习片上硬核ARM Cortex-M3 MCU的开发之前,要先熟悉Microsemi Libero SoC开发环境的使用,可以参考:Microsemi Libero SoC系列教程 关于Microsemi SmartFusion混合型FPGA的介绍,可以参考:Microsemi SmartFusio.

whik1194的博客 8291

lc707设计链表 lc中链表的基本操作

3.不要眼高手低,这些操作都是高中就会的东西,但是真正落实到代码上,确实会出现很多问题,比如对类不熟悉,就会在类这个地方卡住,但通过这道题的学习对py实现链表操作以及类的定义等方面有了初步了解。在增加完一个元素过后,那么他就需要加一,就完成了self.size这个变量的维护,他也就确实有了实际的意义。其实有这种误解完全就是对类的特性不了解,在def init 的时候是在进行初始化,也就是链表最开始的样子,所以虚拟头节点的下面实际上是不可能有任何元素的。2.那既然给他叫head,他不应该是链表的头节点吗?

lll48233的博客 322

什么是 SAP Build Process Automation?

SAP Build Process Automation 是一款综合性的低代码工具,允许企业用户快速开发和自动化端到端业务流程。它整合了工作流管理、任务自动化和人工智能技术,提供了一个易于使用的平台,帮助企业更好地应对现代商业挑战。通过该工具,用户无需具备深厚的编程技能即可创建复杂的业务流程。例如,用户可以使用直观的拖放式界面设计流程、设置触发条件、定义任务分配规则,并通过内置的分析功能对流程效率进行评估。流程建模与设计:提供图形化界面,帮助用户直观地设计业务流程。任务自动化。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1258

代码随想录算法训练营Day03-链表 | LC203移除链表元素、LC707设计链表、LC206反转链表 | Java代码实现

拖延症犯了,哈哈,拖了一天链表算是比较熟悉,不过思路还是不够清晰,应避免逻辑重复,编码速度有待加强。

m0_72781813的博客 822

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

代码随想录算法训练营第三天 | lc.203 移除链表元素 | lc.707. 设计链表 | lc. 206.反转链表

什么是链表,链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。链表的入口节点称为链表的头结点也就是head。如图所示:数组在内存中是物理形式的连续分配,而链表是逻辑上的连续链表的定义链表的操作主要涉及增、删、改,关键就是调整next指针指向的ListNode。

senny_的博客 555

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

【代码随想录】LC 707.设计链表

本文介绍了如何设计一个链表类,实现获取节点值、头部插入、尾部插入、指定位置插入和删除节点等操作。关键点包括:使用虚拟头节点统一操作,处理边界条件如非法索引,维护链表长度变量。具体实现中,获取节点需遍历到目标位置;插入操作调整指针指向新节点;删除操作需释放内存。注意链表索引从0开始,合法范围为[0, len-1],插入时允许在尾部(index=len)操作。代码采用C++实现,通过结构体定义节点,构造函数初始化成员变量。

你的博客 365

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

代码随想录算法训练营第三日| LC203移除链表元素, LC707设计链表, LC206反转链表

定义两个节点pre和cur,pre指向当前链表头节点的前一位,cur指向头节点。然后先将cur的下一个节点储存为temp后再进行反转的操作。pre和cur都要向前移,最后pre会指向原最后一个节点,即新的头节点。先判断头节点的值是否等于val,然后定义一个current节点。当cur的下一个节点为val时,将cur next删除。

EdisonW8的博客 158

代码随想录算法训练营第三天| LC203. 移除链表元素、LC707. 设计链表、206. 反转链表

代码随想录算法训练营

qq_54892503的博客 3751

lc刷题总结(链表第二次)

【代码】lc刷题总结(链表第二次)

j15941558855的博客 254

算法刷题Day3 - 链表part1|链表基础|LC203. 移除链表元素|LC707. 设计链表|LC206. 反转链表

在我第一次写的时候疏忽了一个细节,在判断下一个节点是删除对象并且改动next指向的时候不应该把current向后移,因为有可能next所指向的新的节点也是删除对象,直接后移就相当于跳过了,因此要保证检查完下一个不是删除对象的时候current才能往后移。移除链表中的元素,本质上就是改动移除元素的前一个节点的下个指针直接指向移除元素的下一个节点。注意插入节点的操作常犯的错就是步骤的问题,可能会直接把前一个节点之间连接到新的节点,但是新的节点想要链接到下一个节点的时候发现取不到了。链表也有不同的类型,如。

willc18的博客 442

力扣记录:链表——203 移除链表元素,707 设计链表

leetcode做题记录:链表——203 移除链表元素,707 设计链表

Kiwi_fruit的博客 486

算法刷题 Day3 链表 LC.203 LC.707 LC206

算法刷题Day3 链表部分

yp11110的博客 311

代码随想录算法训练营第三天|LC203.移除链表元素|LC707.设计链表|LC206.反转链表

链表的基础和链表节点的产出和设计;

weixin_49494409的博客 454

算法训练营打卡Day3 | 203.移除链表元素 707.设计链表 206.反转链表

如果cur.next.next为null的话cur.next.val不存在会报错,也是这个原因所以cur.next.val == val时,因为cur.next.next还没有被检查过,所以不需要移动指针cur=cur.next。= null因为操作中会更新cur.next = cur.next.next,不确定cur.next.next是否为null。为什么要保存一下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了第一个节点了。

weixin_51540348的博客 221

代码随想录算法营day3-链表-LC:203-移除;707-设计;206-反转

定义: 数据+指针。最后一个指针指向null。- 类型:单链表(一个指针);双链表(双指针,指向前后node);循环链表(一个环);- 储存方式:散乱分布 & 不连续,全靠指针链接,所以分配机制取决于操作系统的内存管理class ListNode { //类名 :Java类就是一种自定义的数据结构int val;//数据 :节点数据//对象 :引用下一个节点对象。在Java中没有指针的概念,Java中的引用和C语言的指针类似。

sutongfans的博客 1366

代码随想录算法训练营第三天 | LC203.移除链表元素、LC707.设计链表、LC206.反转链表

203.移除链表元素文档>203.移除链表元素 >707.设计链表 >206.反转链表 >203.移除链表元素。

weixin_43730667的博客 171
上一篇: 优快云线上竞赛编程第六期参赛心得
下一篇: 算法笔记-lc-1652. 拆炸弹(简单)
Hell_potato777
博客等级 码龄6年 47粉丝 106原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值