leetcode链表相关题目

文章目录

  • 1.移除链表元素
    • 方法1:
    • 方法2
  • 2.合并两个有序链表
  • 3.链表的中间节点
    • 方法1
    • 方法2
  • 4.反转单链表
    • 方法1
    • 方法2
  • 5.分割链表
  • 6.链表中的倒数第k个节点
    • 方法1:
    • 方法2:
  • 7.环形链表的约瑟夫问题
  • 8.链表的回文结构
  • 9.相交链表
    • 方法1
    • 方法2:
  • 10.环形链表
  • 11.环形链表Ⅱ
  • 12.随机链表的复制

在这里插入图片描述
链表学习完以后,来做点相关题目吧

1.移除链表元素

在这里插入图片描述

方法1:

在原链表的基础上直接删除指定元素

  • 若当前节点要删除的节点,则将其前驱节点指向当前节点的下一个节点
  • 若当前节点不是要删除的节点,前驱节点指向当前节点,当前节点后移
  • 特殊情况:
    • 循环判断,若头节点是要删除的节点,则将头节点后移
    • 头节点不为空
struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* cur = head;struct ListNode* prev = head;//判断头节点while(head && head->val == val){head = head->next;}//链表为空if(head == NULL){return NULL;}//正常情况while(cur){if(cur->val == val){prev->next = cur->next;}else{prev = cur;}cur =  cur->next;}return head;
}

方法2

创建一个新的链表存放未删除的元素

  • 先创建一个虚拟的头节点,指向新链表,同时记录该链表的尾
  • 若当前节点要删除的元素,直接后移
  • 若当前节点不是要删除的元素,连接到新链表的尾后
  • 将新链表尾节点的next置为空(断开与原链表的连接)
struct ListNode* removeElements(struct ListNode* head, int val) {//设置新链表的头struct ListNode* newhead = (struct ListNode*)malloc(sizeof(struct ListNode));newhead->val = -1;newhead->next = NULL;struct ListNode* cur = head;struct ListNode* tail = newhead;while(cur){if(cur->val == val){cur = cur->next;}else{tail->next = cur;tail = tail->next;cur = cur->next;}}//将新链表与原链表断开tail->next = NULL;struct ListNode* ret = newhead->next;free(newhead);newhead = tail = NULL;return ret;
}

2.合并两个有序链表

在这里插入图片描述

创建一个新的链表

  • 两个指针分别指向两个链表
  • 将两指针所指向的元素的较小值连接到新链表的尾
  • 若有一个指针走到空,则将另一个指针连接到新链表的尾
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {//定义新链表的头struct ListNode* newhead = (struct ListNode*)malloc(sizeof(struct ListNode));newhead->val = -1;newhead->next = NULL;struct ListNode* tail = newhead;//比较链表元素while(list1 && list2){if(list1->val < list2->val){tail->next = list1;tail = tail->next;list1 = list1->next;}else{tail->next = list2;tail = tail->next;list2 = list2->next;}}//若有一个链表为空,则连接另一个if(list1){tail->next = list1;}else{tail->next = list2;}struct ListNode* ret = newhead->next;free(newhead);newhead = tail = NULL;return ret;
}

3.链表的中间节点

在这里插入图片描述

方法1

统计链表长度,计算出中间位置;再寻找中间位置

struct ListNode* middleNode(struct ListNode* head) {struct ListNode* cur = head;int len = 0;while(cur){len++;cur = cur->next;}int count = 0;cur = head;while(count < (len / 2)){count++;cur = cur->next;}return cur;
}

方法2

快慢指针法:一个指针一次走一步,一个指针一次走两步。当快指针尾空或者快指针的next为空,那么慢指针所指向的元素就是中间元素。
在这里插入图片描述

struct ListNode* middleNode(struct ListNode* head) {struct ListNode* slow = head;struct ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;
}

4.反转单链表

在这里插入图片描述

方法1

定义一个新的头节点,然后遍历链表,采取头插
在这里插入图片描述

struct ListNode* reverseList(struct ListNode* head) {struct ListNode* newHead = (struct ListNode*)malloc(sizeof(struct ListNode));newHead->val = -1;newHead->next = NULL;while(head){//先记录后继节点struct ListNode* next = head->next;//头插head->next = newHead->next;newHead->next = head;//节点后移head = next;}return newHead->next;
}

方法2

原地直接反转

  • 先记录当前节点的后继节点,以便节点后移
  • 当前节点指向其前驱节点
  • 前驱节点后移
  • 当前节点后移
  • prev即为反转后新的头

在这里插入图片描述

struct ListNode* reverseList(struct ListNode* head) {struct ListNode* next = NULL;struct ListNode* prev = NULL;struct ListNode* cur = head;while(cur){next = cur->next;cur->next = prev;prev = cur;cur = next;}return prev;
}

5.分割链表

在这里插入图片描述
思路:

  • 给定两个新的链表,一个放小于X的元素,一个放大于X的元素
  • 元素尾插至新链表
  • 将两个新链表相连

在这里插入图片描述

struct ListNode* partition(struct ListNode* head, int x){struct ListNode* minHead = (struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* maxHead = (struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* minTail = minHead;struct ListNode* maxTail = maxHead;struct ListNode* cur = head;while(cur){if(cur->val < x){minTail->next = cur;minTail = minTail->next;}else{maxTail->next = cur;maxTail = maxTail->next;}cur = cur->next;}//防止成环maxTail->next = NULL;minTail->next = maxHead->next;struct ListNode* ret = minHead->next;free(minHead);free(maxHead);return ret;
}

6.链表中的倒数第k个节点

在这里插入图片描述

方法1:

思路:倒数第k就是正数第n-k+1个(n为链表长度)
特殊情况:

  • k应该小于链表长度
  • k不能为0
  • 链表不能为空
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k) {struct ListNode* cur = pListHead;int len = 0;//求链表的长度while (cur){len++;cur = cur->next;}//特殊情况判断//1.k不能大于链表长度//2.k不能为0//3.链表不为空if (k > len || k == 0 || pListHead == NULL){return NULL;}//倒数第k个就是正数第n-k+1个int n = 1;len = len - k + 1;cur = pListHead;while (n != len){n++;cur = cur->next;}return cur;
}

方法2:

快慢指针:快指针先走k步,然后快慢一起走
在这里插入图片描述

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {struct ListNode* fast = pListHead;struct ListNode* slow = pListHead;//快指针先走k步while(k--){//fast不能走出链表(k符合)if(fast){fast = fast->next;}else {return NULL;}}while(fast){slow = slow->next;fast = fast->next;}return slow;
}

7.环形链表的约瑟夫问题

在这里插入图片描述
解题思路:

  • 构建环形链表,给每个节点编号
  • 逢m就删除节点,再从新报数

在这里插入图片描述

typedef struct ListNode  ListNode;//创建节点
ListNode* CreatNode(int x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));newnode->val = x;newnode->next = NULL;return newnode;
}//构建环
ListNode* CreatCircle(int n)
{ListNode* head = CreatNode(1);ListNode* tail = head;//连续创建节点for(int i=2; i<=n; i++){ListNode* newnode = CreatNode(i);//连接节点tail->next = newnode;tail = tail->next;}//成环tail->next = head;//返回尾节点的目的是:防止第一个元素就是要删除的元素return tail;
}int ysf(int n, int m ) {ListNode* prev = CreatCircle(n);ListNode* cur = prev->next;int count = 1;//有多个节点继续报数,直到剩下一个节点while(cur->next != cur){//逢m就删除if(count == m){prev->next = cur->next;free(cur);cur = prev->next;count = 1;}else {prev = cur;cur = cur->next;count++;}}return cur->val;
}

8.链表的回文结构

在这里插入图片描述
思路:从链表的中间节点逆置后半段,然后比较前半段与后半段是否相等。

  • 快慢指针找链表的中间节点
  • 从中间节点反转单链表
  • 节点比较

在这里插入图片描述
在这里插入图片描述

	//找中间节点ListNode* FindMid(ListNode* A){ListNode* fast = A;ListNode* slow = A;while(fast && fast->next){fast = fast->next->next;slow = slow->next;}return slow;   }//反转ListNode* Reverse(ListNode* mid){ListNode* cur = mid;ListNode* prev = NULL;ListNode* next = NULL;while(cur){next = cur->next;cur->next = prev;prev = cur;cur = next;}return prev;}bool chkPalindrome(ListNode* A) {ListNode* mid = FindMid(A);ListNode* midhead = Reverse(mid);while(midhead){if(A->val == midhead->val){A = A->next;midhead = midhead->next;}else {return false;}}return true;}

9.相交链表

在这里插入图片描述

方法1

将链表A中的每一个节点与链表B中的每一个节点比较,看是否相等。

  • 若相等,则返回相等的节点
  • 若所有节点都不相等,则链表不相交。
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode* curA = headA;struct ListNode* curB = headB;while(curA){curB = headB;while(curB){//若节点相等,直接返回相等节点if(curA == curB){return curA;}curB = curB->next;}curA = curA->next;}//A中每一个节点都与B比较完毕,仍无交点return NULL;
}

方法2:

分别计算两链表长度,长的先走长度差步,然后再一起走,判断是否相等。

  • 再求链表长度的同时,若两链表的最后一个节点相等,则二者一定相交
struct ListNode* getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode* curA = headA;struct ListNode* curB = headB;int lenA = 0;int lenB = 0;//先计算链表各自的长度,都少计算一个while(curA->next){lenA++;curA = curA->next;}while(curB->next){lenB++;curB = curB->next;}//若不相交,直接返回空if(curA != curB){return NULL;}//算长度差int  gap = abs(lenA - lenB);struct ListNode* longList = headA;struct ListNode* shortList = headB;if(lenA < lenB){longList = headB;shortList = headA;}//长的先走长度差步while(gap--){longList = longList->next;}//同时走,找交点while(longList && shortList){if(longList == shortList){return shortList;}longList = longList->next;shortList = shortList->next;}return NULL;
}

10.环形链表

在这里插入图片描述
思路:快慢指针。

  • 一个指针一次走一步,一个指针一次走两步
  • 若快指针走到了空,则不带环
  • 若快指针与慢指针相遇,则带环
bool hasCycle(struct ListNode *head) {struct ListNode * fast = head;struct ListNode * slow = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast){return true;}}return false;
}

为什么这样可以呢?
在这里插入图片描述

为什么不是一个走1步一个走3步?一个走1步一个走4步?一个走1步一个走6步?…

在这里插入图片描述
在这里插入图片描述

若N为奇数,C-1也为奇数则永远追不上(存在这种情况吗?)

在这里插入图片描述
所以,一步两步走是最保险也是最简单的方式,不会错过。

11.环形链表Ⅱ

在这里插入图片描述
思路:快慢指针,找到二者的相遇点。再使用两指针,从相遇点和链表头开始走,二者相遇点就是入环点

struct ListNode *detectCycle(struct ListNode *head) {struct ListNode* slow = head;struct ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast){struct ListNode* meet = slow;while(meet != head){meet = meet->next;head = head->next;}return meet;}}return NULL;
}

原理

在这里插入图片描述

12.随机链表的复制

在这里插入图片描述
在这里插入图片描述
本题的难点在于random的指向难以找到
思路:

  • 在原链表每个节点的后面尾插一个新的节点
  • 根据原链表,找到新链表的random指向
  • 将新链表的节点与原链表分离,恢复原链表

第一步:连接新节点
在这里插入图片描述

第二步:搞清random指向
新链表random就是原链表random的next!!!
在这里插入图片描述
第三步:将新链表从原链表上摘下来
在这里插入图片描述

struct Node* copyRandomList(struct Node* head) {struct Node* cur = head;//插入新节点while(cur){struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));//连接新节点newnode->val = cur->val;newnode->next = cur->next;cur->next = newnode;//原链表后移cur = cur->next->next;}//randomcur = head;while(cur){struct Node* newnode = cur->next;if(cur->random == NULL){newnode->random = NULL;}else{newnode->random = cur->random->next;}cur = cur->next->next;}//摘新链表struct Node* newhead = (struct Node*)malloc(sizeof(struct Node));newhead->next = NULL;newhead->random = NULL;struct Node* tail = newhead;cur = head;while(cur){//尾插新链表struct Node* newnode = cur->next;tail->next = newnode;tail = tail->next;//恢复原链表cur->next = newnode->next;cur = cur->next;}return newhead->next;
}

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

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

相关文章

专业课145+总分410+华南理工大学811信号与系统考研经验华工电子信息与通信,真题,大纲,参考书。

大家好&#xff0c;今年考研顺利上岸华南理工大学&#xff0c;专业课811信号与系统145&#xff08;只差一点满分&#xff0c;有点遗憾&#xff0c;专业我跟着Jenny老师复习投入时间和精力和数学差不多&#xff0c;华工专业课难度中等&#xff0c;是一个总分提高很好的突破口&am…

【JavaScript 漫游】【014】正则表达式通关

文章简介 JS 语言中的 RegExp 对象提供正则表达式的功能。本篇文章旨在对该对象的相关知识点进行总结。内容包括&#xff1a; 正则表达式概述RegExp 对象的实例属性RegExp 对象的实例方法字符串与正则表达式相关的实例方法正则表达式匹配规则 概述 正则表达式的概念 正则表…

第三节课[LangChain]作业

文章目录 前言实践搭建向量知识库 前言 本次作业虽然是第三节课作业&#xff0c;但是在第四次作业之后才完成&#xff0c;所以用的是经过自我认知微调的小助手权重。 使用**诡秘之主和宿命之环小说&#xff08;仅用于学习和研究&#xff09;**以及设定集、百度百科&#xff0c…

【开源】JAVA+Vue.js实现天然气工程业务管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、使用角色3.1 施工人员3.2 管理员 四、数据库设计4.1 用户表4.2 分公司表4.3 角色表4.4 数据字典表4.5 工程项目表4.6 使用材料表4.7 使用材料领用表4.8 整体E-R图 五、系统展示六、核心代码6.1 查询工程项目6.2 工程物资…

414. Third Maximum Number(第三大的数)

题目描述 给你一个非空数组&#xff0c;返回此数组中第三大的数 。如果不存在&#xff0c;则返回数组中最大的数。 问题分析 注意要查找的数是数组中第三大的数&#xff0c;相同大小的数算一个&#xff0c;对于此问题可以采用先将数组排序然后查找第三大的数采用排序的方式最…

如何解决利用cron定时任务自动更新SSL证书后Nginx重启问题

利用cron定时任务自动更新SSL证书后&#xff0c;用浏览器访问网站&#xff0c;获取到的证书仍然是之前的。原因在于没有对Nginx进行重启。 据说certbot更新完成证书后会自动重启Nginx,但显然经我检测不是这回事儿。 所以我们需要创建一bash脚本&#xff0c;然后定时调用这个脚…

Vue核心基础5:数据监测、收集表单数据、过滤器

1 数据监测 【代码】 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>总结</title><scrip…

ChatGPT高效提问—prompt实践

ChatGPT高效提问—prompt实践 ​ 探索prompt在实际生活中的各种应用&#xff0c;旨在帮助理解和掌握如何将之前学到的prompt基础和技巧应用到具体实践中&#xff0c;从而在各个领域实现人工智能的价值。 ​ 通过生动的案例&#xff0c;发现并挖掘ChatGPT和prompt的无穷潜力。…

一个小而实用的 Python 包 pangu,实现在中文和半宽字符(字母、数字和符号)之间自动插入空格

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一个小巧的库&#xff0c;可以避免自己重新开发功能。利用 Python 包 pangu&#xff0c;可以轻松实现在 CJK&#xff08;中文、日文、韩文&#xff09;和半宽字符&#xff08;字母、数字和符号&#xf…

电路设计(15)——篮球赛24秒违例倒计时报警器的proteus仿真

1.设计要求 设计、制作一个篮球赛24秒违例倒计时报警器。要求&#xff1a; &#xff08;1&#xff09;具有倒计时功能。可完整实现从“24”秒开始依序倒计时并显示倒计时过程&#xff0c;显示时间间隔为1秒。 &#xff08;2&#xff09;具有消隐功能。当“24”秒倒计时…

nodejs切换版本

sudo n 18.17.0 sudo n然后键盘上下选择

PgSQL内核特性 - push-based pipeline 执行引擎

PgSQL内核特性 - push-based pipeline 执行引擎 数据库的SQL执行引擎负责处理和执行SQL请求。通常情况下&#xff0c;查询优化器会输出物理执行计划&#xff0c;一般由一系列的算子组成。当前&#xff0c;有两种算子流水线构建方式&#xff1a;1&#xff09;需求驱动的流水线&a…

AJAX——常用请求方法

1 请求方法 请求方法&#xff1a;对服务器资源&#xff0c;要执行的操作 2 数据提交 场景&#xff1a;当数据需要在服务器上保存 3 axios请求配置 url&#xff1a;请求的URL网址 method&#xff1a;请求的方法&#xff0c;GET可以省略&#xff08;不区分大小写&#xff09; …

防火墙安全策略及nat实验

要求一&#xff1a;生产区的设备在工作时间访问dmz区,仅可访问http服务器 要求二&#xff1a;办公区可以全天访问dmz区&#xff0c;其中10.0.2.20可以访问FTP服务器和HTTP服务器&#xff0c;10.0.2.10仅可以ping通10.0.3.10 要求三&#xff1a;办公区在访问服务器区时采用匿名认…

jsp课程教学管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 课程教学管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0…

【漏洞复现】狮子鱼CMS文件上传漏洞(wxapp.php)

Nx01 产品简介 狮子鱼CMS&#xff08;Content Management System&#xff09;是一种网站管理系统&#xff0c;它旨在帮助用户更轻松地创建和管理网站。该系统拥有用户友好的界面和丰富的功能&#xff0c;包括页面管理、博客、新闻、产品展示等。通过简单直观的管理界面&#xf…

基于LLM的业务流程自动化

在当今竞争激烈的商业环境中&#xff0c;业务流程&#xff08;尤其是文档处理工作流程&#xff09;的自动化对于寻求提高效率和减少人工错误的公司来说变得至关重要。 传统方法往往难以跟上任务的数量和复杂性&#xff0c;而人工主导的流程速度缓慢、容易出错&#xff0c;并且可…

零基础学编程从哪里入手,编程实例分享,配件进出库管理系统软件

零基础学编程从哪里入手&#xff0c;编程实例分享&#xff0c;配件进出库管理系统软件 一、前言 对于刚学编程的人来说&#xff0c;多看看现有的软件实例对自己学开发软件是很有帮助的。 下面分享的实例以配件进出库管理系统软件为例说明。 软件文件下载可以点击最下方官网…

线性代数的本质——1 向量

向量是线性代数中最为基础的概念。 何为向量&#xff1f; 从物理上看&#xff0c; 向量就是既有大小又有方向的量&#xff0c;只要这两者一定&#xff0c;就可以在空间中随便移动。 从计算机应用的角度看&#xff0c;向量和列表很接近&#xff0c;可以用来描述某对象的几个不同…

S32 Design Studio的PE工具

S32 Design Studio软件是NXP公司专门为了方便用户开发S32K1系列芯片的IDE&#xff0c;跟Eclipse比较像。里面有个配套的图形工具Processor Expert&#xff0c;会产生一个后缀名为pe的文件&#xff0c;跟ST的cubemx作用类似。 双击pe文件即可打开pe界面&#xff0c;生成的文件将…