有关于链表的题目(打印链表、翻转链表、合并两个排序链表)

Algorithm:【算法进阶之路】之算法面试刷题集合—链表的简介、相关算法题目集合(链表相加、链表的部分翻转、链表划分、链表去重、重复元素全部删除) ​ Algorithm:【算法进阶之路】之算法面试刷题集合—链表的简介、相关算法题目集合(链表相加、链表的部分翻转、链表划分、链表去重、重复元素全部删除) 目录 链表的简介 与链表相关的习题 早期—链表案例(C++语言实现) 链表的简介 简介 在链式存储结构中,无论是循环链表还是线性链表,插入和删除元素时,只需要改变相应位置的结点指针即可,头指针和尾指针无法确定链表的长度。 特点 与链表相关的习题 企业题库(按照考试频率):CodeTop企业题库 Gi 阅读详情

题目一:输入一个链表,从尾到头打印链表每个节点的值。

采用c++:

方法一:开辟栈空间,将链表从头到尾放入栈中,然后再打印栈

代码如下:

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        //从尾到头将结果先放入栈中,然后输出栈,实现不改变链表的结构从尾到头输出
        std::stack<ListNode *> nodes;
        ListNode *Phead = head;
        vector<int> vec;
        while(Phead != NULL)
        {
            nodes.push(Phead);
            Phead = Phead->next;           
        }
        while(!nodes.empty()){
            Phead = nodes.top();
            vec.push_back(Phead->val);
            nodes.pop();
        }
        return vec;
    }
};

由于递归的本质就是一个栈结构,想到用栈实现,所以用递归也可以实现,访问每个结点时,先递归输出它后面的结点,再输出该结点自身,这样链表的输出结果就会反过来。

代码如下:

vector<int> vec;
   vector<int> printListFromTailToHead(ListNode* head) {
   if(head == NULL) return vec;
   printListOfRecursion(head); 
        return vec;  
    }
    void printListOfRecursion(ListNode* head)
    {
        if(head != NULL)
        {
            if(head->next != NULL)
            {
                printListFromTailToHead(head->next);
            }
            vec.push_back(head->val);
        }
    }


题目二: 输入一个链表,输出该链表中倒数第k个结点

解题思路:此题可以利用上一题的解题思路,将链表先放入栈中,然后输出栈中的第k个值

栈结构如下所示:

struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};

代码如下所示:

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
     //先放入栈中,然后再输出栈中第k个值就是链表中的倒数第k个值
	stack<ListNode *> FindKthStack;
        int flag = 0;
        while(pListHead != NULL)
        {
            FindKthStack.push(pListHead);
            pListHead = pListHead->next;    
            flag++;
        }
        if(flag < k || k == 0) //边界问题,没有考虑当为k==0 或者 链表的长度小于k的值,思考了好久的问题,思路没有错误,但是在细节上没有考虑到
        {
            return NULL;         
        }
        for(int i = 1;i <= (k - 1);i++)
        {
             if(!FindKthStack.empty())
                 FindKthStack.pop();
        }   
        return  FindKthStack.top();
    } 
};


不同栈进行存储,用vector进行存储,输出倒数第k个值,就是数组的长度减k,具体代码如下:

 vector<ListNode *> FindKthVector;
        while(pListHead)
        {
            FindKthVector.push_back(pListHead);
            pListHead = pListHead->next;           
        }
        if(FindKthVector.size() < k || k == 0 )
            return NULL;
        return FindKthVector[FindKthVector.size()-k];


但是这两种方法会增加额外的空间,所以并不是最好的解题方法,可以采用快慢指针的方法,不会产生额外的空间,时间复杂度也没有增加:

1、定义两个指针L1,L2 ;

 2、先让L2走k-1步;

3、然后L1,L2同时走直至L2走到链表尾端为止,则L1现在所指的指针就是倒数第k个指针

具体代码如下:

ListNode *L1 = pListHead,*L2 = pListHead;
        unsigned int i = 0;
        if(pListHead == NULL || k == 0)
        {
            return NULL;          
        }
        for(int i = 0;i < k-1;i++)
        {
            if(L2->next == NULL){return NULL;}
            else{  L2 =  L2->next;  }                    
        }
        while(L2->next != NULL)
        {
            L1 = L1->next;
            L2 = L2->next;
        }
    return L1; 

题目三:输入一个链表,反转链表后,输出链表的所有元素。

解题思路:定义三个指针,头pre,尾 nail 和中间指针 cur

核心代码就4句话:

            nail = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nail; 

尾指针先保存中间指针的下一个结点,然后将前指针赋值给中间指针的下一个结点,这两步实现指针指向的逆转;

后面两句话分别让前指针和中间指针往后移一步,实现遍历整个链表;

完整代码如下:

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == NULL)
        {
            return NULL;            
        }
        //定义三个指针,nail表示正方向的下一个指针,pre表示反向的下一个指针,cur表示中间的指针
        ListNode* pre,*cur,*nail;
        pre = pHead;
        cur = pHead->next;
        while(cur){
            nail = cur->next;
            cur->next = pre;
            pre = cur;//反向的指针前进一个
            cur = nail; //正向的指针前进一个           
        }
        pHead->next = NULL;//pHead变成尾指针
        pHead = pre; //pre为头指针赋值给pHead
        return pHead;
    }
};

题目四:合并两个排序的链表

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

可以选择递归和非递归的调用方法,递归方法比较简单也很好理解

递归方法:使用递归方法,首先要想好结束条件

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1 == NULL && pHead2 != NULL){ return pHead2;}     //边界问题,要考虑清楚
        else if(pHead1 != NULL && pHead2 == NULL){ return pHead1;}//边界问题,要考虑清楚
        else if(pHead1 == NULL && pHead2 == NULL){ return NULL;}  //边界问题,要考虑清楚
       //递归调用判断连个链表哪个是最小值,然后赋值给mergeList的下一个值,这个函数利用递归很好理解
        ListNode * mergeList;
        if(pHead2->val < pHead1->val)
        {
           mergeList = pHead2;
           pHead2 = pHead2->next;
           mergeList->next = Merge(pHead1,pHead2); 
        }
        else
        {
           mergeList = pHead1;
           pHead1 = pHead1->next;
           mergeList->next = Merge(pHead1,pHead2);
        }        
        return mergeList;
    }
};

非递归方法:考虑比较多一点,首先要判断头结点,然后循环中间结点,然后对尾结点进行赋值

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1 == NULL && pHead2 != NULL){ return pHead2;}     //边界问题,要考虑清楚
        else if(pHead1 != NULL && pHead2 == NULL){ return pHead1;}//边界问题,要考虑清楚
        else if(pHead1 == NULL && pHead2 == NULL){ return NULL;}  //边界问题,要考虑清楚
        //非递归方法
        ListNode* pHead = NULL;      
        ListNode* pre = NULL;
        //取较小的值作头节点
        if(pHead2->val <= pHead1->val)
        {
            pre = pHead2;
            pHead2 = pHead2->next;
        }
        else
        {
            pre = pHead1;
            pHead1 = pHead1->next;
        }
        //开始遍历合并
        pHead = pre;
        while(pHead1 != NULL && pHead2 != NULL )
        {            
                if(pHead2->val <= pHead1->val)
                {                    
                    pHead->next = pHead2;
                    pHead2 = pHead2->next;
                    pHead = pHead->next;
                }
                else
                {
                    pHead->next = pHead1;
                    pHead1 = pHead1->next;
                    pHead = pHead->next;
                }                                    
        }
        //判断是否到了尾端
        if(pHead1 == NULL)
        {
            pHead->next = pHead2;
                        
        }
        if(pHead2 == NULL)            
        {
            pHead->next = pHead1; 
        }
        return pre; 
    }
};




别再死磕NFP了!用Python+遗传算法搞定异形件自动排版(附完整代码) 本文介绍了如何利用Python和遗传算法实现异形件智能排版,解决传统NFP方法计算复杂的问题。通过Shapely库处理几何运算和DEAP库搭建遗传算法框架,结合模拟退火策略避免局部最优,显著提升材料利用率。附完整代码和优化技巧,适用于服装裁剪、金属加工等行业。 阅读详情

相关推荐

应用处理器(AP)、系统级芯片(SoC)与微控制器(MCU)的区别与联系

应用处理器(AP)、系统级芯片(SoC)与微控制器(MCU)的区别与联系

a_zxswer的博客 1689

校招选择题汇总【链表(2)】含答案解析

有问题的下方评论或私信 1.链式存储的存储结构所占存储空间(A) A.分两部分,一部分存节点值,另一部分存表示节点间关系的指针 B.只有一部分,存放节点值 C.只有一部分,存储表示节点间关系的指针 D.分两部分,一部分存放节点值,另一部分存放节点所占单元数 解析:链式表中节点分两部分 数据域和指针域 2.链表不具有的特点是(B) A.插入、删除不需要移动元素 B.可随机访问任...

Teacher_HENG 6823

汇川AM402、H3U和上位机C#ModebusTcp通讯

目录一、测试任务二、测试环境三、PLC工程1、组态配置2、ip地址、端口号 3、全局变量定义四、C#端Winform程序创建1创建主界面 2、创建子窗口 3、运行生成,界面效果4、Modebus协议说明5、Modebus操作说明六、测试1、寄存器读测试 2、MW1300寄存器的BIT位3、写寄存器测试4、PLC断电或者断网 七、工程下载连接1、PLC作为ModebusTCP端,端口号都是502,PC端上位机软件作为TcpClient去连接多台PLC。PC端读写PLC寄存器。2、PC端在有的PLC断电、断网的

panjinliang066333的博客 2万+

校招选择题汇总【链表(1)】含答案解析

有问题的下方评论或私信 1.线性表采用链式地址时,其地址(D) A.必须是连续的 B.一定是不连续的 C.部分地址必须是连续的 D.连续与否均可以 解析:线性表两种实现方式,一个用数组,一个用链表。数组中存储空间地址是必需连续的,用链表的话,每创建一个节点其地址是由计算机随机分配的,所以地址不一定连续,但既然是随机的,怎么就不能够随机出连续的可能呢0_0?其实可以这么理解,数组是特...

Teacher_HENG 4105

别再手动下单了!用Python+EasyTrader+同花顺,5分钟搞定你的第一个自动化交易机器人

本文详细介绍了如何使用Python和EasyTrader结合同花顺客户端快速构建自动化交易机器人。从环境配置到实战脚本编写,涵盖自动打新、条件单、跟单策略等核心功能,并分享性能优化与风险控制技巧,帮助投资者高效实现自动化交易。

weixin_30381317的博客 398

2025红队实战:Win11环境下ZAP、CobaltStrike与免杀套件深度评测

在网络安全领域,渗透测试与红队行动是评估系统防御能力的关键手段。其核心原理在于模拟真实攻击者的技术与流程,以发现潜在的安全漏洞。这项技术的价值在于主动识别风险,提升整体安全防护水平,广泛应用于企业安全评估、漏洞挖掘和攻防演练等场景。随着Windows 11系统普及,其增强的安全机制(如内存完整性、基于虚拟化的安全)对传统攻击工具链提出了新的挑战。本文聚焦于**CobaltStrike二开版**与**免杀套件**在Win11环境下的实战应用与深度对抗,探讨如何优化工具链以应对现代端点检测与响应(EDR)和高级

weixin_29315091的博客 308

C语言【数据结构】顺序表、链表【选择题】

目录 1. 在长度为 n 的顺序表下标为 i 的位置前插入一个元素(1 ≤ i ≤ n+1),元素的移动次数为(B)2.下列关于链表的说法哪个是正确的?(A)3.在单链表指针为p的结点之后插入指针为s的结点,正确的操作是(C)4.下列判断循环双向链表为空的语句中,正确的是(C)5. 在长度为n(n>1)的单链表上,设有头和尾两个指针,执行(D)操作与链表的长度有关。6.关于链表和顺序表间的区别,叙述错误的是(D)7.在一个循环双向链表中,要在p所指的节点之前插入s所指节点,以下代码正确的执行次序是(A)

冰果滴的博客 4877

dreamerv3复现教程

由于dreamerv3存在很多版本冲突问题,所以很难直接使用和复现。

无人机飞啊飞啊飞 2832

链表选择题练习

1、已知L是带头节点的单链表,节点P既不是头节点(第一个节点),也不是尾节点,删除P节点直接后继节点的语句序列是(C) A、P = P -> next; B、P -> next = P; C、P - > next = P -> next -> next; D、P=P -> next -> next; 题解: 将当前节点的下一个的下一个赋给当前的P -&gt...

master_1997的博客 2941

Qwen2.5-7B大模型实战:从零部署到高效推理全流程解析

本文详细解析了Qwen2.5-7B大模型从零部署到高效推理的全流程。内容涵盖环境准备、模型下载、使用Transformers进行核心对话推理,并深入介绍了vLLM与TGI生产级服务部署、GPTQ/AWQ量化技术以降低显存消耗,以及llama.cpp、Ollama等本地推理方案。旨在帮助开发者快速掌握部署技巧,实现大模型在消费级硬件上的高效运行。

weixin_29061425的博客 490

使用 Simulink 进行电力电子系统的大信号模型仿真

电力电子系统(Power Electronics System)包括各种功率转换器(如 DC-DC 转换器、逆变器等)。这些设备中的关键组件(如 MOSFET、IGBT、电容器、电感器等)不仅影响系统的性能,还直接关系到系统的稳定性、效率和可靠性。因此,在设计阶段进行详细的建模和仿真至关重要。大信号模型仿真的目的是通过模拟系统在非线性条件下的真实行为,评估其瞬态响应、稳态性能以及对不同负载和输入电压变化的响应。通过本教程,我们介绍了如何使用 Simulink 进行电力电子系统的大信号模型仿真。背景介绍。

xiaoheshang_123的博客 303

单链表反转

单链表的翻转是一道很基本的算法题。         方法1:将单链表储存为数组,然后按照数组的索引逆序进行反转。         方法2:使用三个指针遍历单链表,逐个链接点进行反转。         方法3:从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾。         方法1的问题是浪费空间。方法2和方法3效率相当。一般方法2

qq_37655087的博客 248

想使用dify实现docx文档的自动生成?试了一圈,感觉还是根据python-docx更靠谱

在软件开发过程中,需求文档、设计文档等材料的编写是每个开发者都绕不开的工作。最近笔者接到一个需要批量生成标准化需求文档的任务,尝试了目前热门的低代码工具Dify后,发现对于稍微复杂格式的文档生成需求(例如文本居中这么简单的需求),最终还是回归到基于python-docx库的解决方案。本文将分享两种技术路线的对比实践。

xiezhipu的博客 2547

剑指offer-链表相关

剑指offer面试常考手撸算法题-链表篇 1. 从头到尾打印链表 1 class Solution { 2 public: 3 // 可以先压栈,再出栈到vector 4 // 时间/空间:O(n) 5 vector<int> printListFromTailToHead(ListNode* head) { 6 ...

yocichen 266

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【LeetCode刷题日记】链表类题目常见题型

文章目录[21. 合并两个有序链表](https://leetcode-cn.com/problems/merge-two-sorted-lists/)[19. 删除链表的倒数第 N 个结点](https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/)[2. 两数相加](https://leetcode-cn.com/problems/add-two-numbers/)[24. 两两交换链表中的节点](https://leetcod

qq_41854911的博客 613

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【剑指Offer】解题思路拆解Java版——第三期

下面这段时间带来的是对于剑指Offer(第二版)一书中的算法题目进行阅读并分享。原书中一共66道题目,我们就一天11道,用六天的时间来进行讲解,最后一天来个总结,争取在一周的时间内介绍完这66道经典题目。要是喜欢的欢迎关注公众号《Java冢狐》来追更! 今天是剑指Offer的第三期, 另外由于原书是C++代码编写而成,这边我们用Java来实现一遍,顺便说一下相关的面试知识点,一起进行面试前的复习。希望大家能够喜欢。 另外有些地方的讲解可能并不是十分到位,在此更推荐更大家去看原书。 那么话不多少,让我们开始今

冢狐的私人空间 236

STM32F407中文手册

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

剑指 Offer(第 2 版)笔记(简单篇)

剑指 Offer(第 2 版)笔记(简单篇)

qq_39493185的博客 1315

字节面试官:连这90道LeetCode算法题都不会也来面试?

给定两个用链表表示的整数,每个节点包含一个数位。这些数位是反向存放的,也就是个位排在链表首部。编写函数对这两个整数求和,并用链表形式返回结果。18. 生成随机数给定一个 0-4 随机数生成器 如何生成 0-6 随机数19. 二叉树的最近公共祖先:中等给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。

2401_85405758的博客 684

链表介绍及题目练习

链表介绍及题目练习 一、链表介绍 链表实际上是线性表的链式存储结构,与数组不同的是,它是一组任意的存储单元来存储线性表中的数据,存储单元不一定是连续的,且链表的长度不是固定的,链表数据的这一特点使其可以非常方便地实现节点的插入和删除操作。 链表的每个元素称为一个节点,每个节点都可以存储在内存中的不同位置,为了表示每个元素与后继元素的逻辑关系,以便构成“一个节点链着一个节点”的链式存储结构,除了存储元素本身的信息外,还要存储其直接后继信息,因此,每个节点都包含两部分,第一部分称为链表的数据域,用于存储元素本身

qq_41074616的博客 305

链表的升序,降序排列及逆转,合并

代码说明: 输入四个数,la为升序链表,再输入四个数,ld为降序链表 若要将la与ld合并成升序链表,则首先将ld逆转成升序链表lb,在构造合并函数lc,具体代码讲解看链表 #include &lt;iostream&gt; #include&lt;stdio.h&gt; #include&lt;stdlib.h&gt; #include&lt;string.h&gt; using namespa...

巴啦啦能量 3290

JS:链表题目(1)——两数相加、合并链表(小顶堆)

2.两数相加 19.删除链表的倒数第 N 个结点 21.合并两个有序链表 23.合并 K 个升序链表 141.环形链表 142.环形链表 II 160.相交链表 876.链表的中间结点 25.K 个⼀组翻转链表 83.删除排序链表中的重复元素 92.反转链表 II 234.回⽂链表 2. 两数相加 (中等) 一次遍历计算完成,需注意: 构建空的头结点,不用处理一开始指针指向null的情况 执行加法,考虑进位的情况。新链表要记得移动。 两个链表不等长 读完两个链表后,最后一次进位仍要处理 21. 合并

ronghwa_lu 739

面试题目集锦--链表

前段时间一直在忙着找工作,在面试中也遇到了大量的算法题目,其中,问的比较多的是二叉树和链表之类的题目,在这里,我就把前段时间写的链表面试题贴出来,当然,由于题目很多,我只是在这里贴出它的类构造,不贴出实现的代码,需要的朋友可以去这里下载(免积分):http://download.youkuaiyun.com/detail/dlutbrucezhang/8062413      如果因为其他别的原因下载不下来的

张勤一 2429

[剑指offer] 14. 链表中倒数第K个节点+翻转+逆序打印+合并两个排序链表 + 链表相交(第一个公共节点) (链表)...

题目描述 输入一个链表,输出该链表中倒数第k个结点。 思路: 两个指针,起始位置都是从链表头开始,第一个比第二个先走K个节点,当第一个走到链表尾时,第二个指针的位置就是倒数第k个节点。(两指针始终相聚k个节点) 注意边界条件: 1.链表不能一开始就是空的。 2.当链表只有5个节点时,若k=5,则返回第1个节点;若K>5,统一返回NULL。 边界条件十分影...

weixin_30355437的博客 103

LeetCode-题目详解(六):链表【链表的中间节点:左半链表的结尾节点】【slow = head | fast = head | while fast and fast.next】

当「乌龟」和「兔子」从链表上的同一个节点开始移动时,如果该链表中没有环,那么「兔子」将一直处于「乌龟」的前方;链表具有天然的递归性,一个链表例如 1->2->3->4->5->NULL ,可以看成头节点(节点值为 1 的节点)后面挂接一个更短的链表(缺少节点值为 1 的节点,以节点值为 2 的节点为头节点) 1->更短的链表,依次类推。这样以来,我们首先使用哈希表进行定位,找出缓存项在双向链表中的位置,随后将其移动到双向链表的头部,即可在 O(1) 的时间内完成 get 或者 put 操作。

u013250861的博客 2336

两个有序链表序列的交集_每日算法题 | 剑指offer 链表专题 (9) 合并两个有序链表...

点击上方“Jerry的算法和NLP”,选择“星标”公众号 重磅干货,第一时间送达题目合并两个有序链表题目要求输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。如输入1->3->5 2->4->6 输出1->2->3->4->5->6解题思路可以把链表当作一个链式数组去对待,那么这...

weixin_39517546的博客 201

Leetcode题目:python 实现链表题目合集(边做边更新)

思路及注意点(新手走的弯路): 1.一定要明确l1,l2链表是不可以在尾部加新节点的,因为最后一个指针值为None。 2.保存结果的链表必须满足在尾部添加节点,因为进位的时候要加1,利用ListNode()可以完成动态添加节点。 3.遍历2个链表,先走完的默认值为0,当另一个也走完的时候,一定要注意不要再加新节点了,此可结果链表的长度等于l1,l2中最长的那个。 4.遍历完后,判断是否需要进位,进位则加一个新节点,并赋值为1。 下面的程序是调试的所有代码。 "=====================..

weixin_43585712的博客 1081
上一篇: 任意非负整数,求1~n之间含有1的整数的个数
下一篇: 用两个栈实现队列 & 两个队列实现栈
Traveling_DING
博客等级 码龄12年 65粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值