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.rhkb.cn/news/256047.html

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

相关文章

EMC学习笔记(二十六)降低EMI的PCB设计指南(六)

降低EMI的PCB设计指南&#xff08;六&#xff09; 1.PCB布局1.1 带键盘和显示器的前置面板PCB在汽车和消费类应用中的应用1.2 敏感元器件的布局1.3 自动布线器 2.屏蔽2.1 工作原理2.2 屏蔽接地2.3 电缆屏蔽至旁路2.4 缝隙天线&#xff1a;冷却槽和缝隙 tips&#xff1a;资料主要…

SCI 1区论文:Segment anything in medical images(MedSAM)[文献阅读]

基本信息 标题&#xff1a;Segment anything in medical images中文标题&#xff1a;分割一切医学图像发表年份: 2024年1月期刊/会议: Nature Communications分区&#xff1a; SCI 1区IF&#xff1a;16.6作者: Jun Ma; Bo Wang(一作&#xff1b;通讯)单位&#xff1a;加拿大多…

python+flask+django农产品供销展销电子商务系统lkw43

供销社农产品展销系统的设计与实现&#xff0c;最主要的是满足使用者的使用需求&#xff0c;并且可以向使用者提供一些与系统配套的服务。本篇论文主要从实际出发&#xff0c;采用以对象为设计重点的设计方法&#xff0c;因此在进行系统总体的需求分时借助用例图可以更好的阐述…

一个三极管引脚识别的小技巧,再也不用对照手册啦

三极管是一个非常常用的器件,时不时的就需要用到他们,有些时候当我们拿到一颗三极管时 ,对于常用的友来说,三极管的引脚可能早已烂熟于心,而对于不常用或者初学者来说,三极管的引脚可以说是今天记下明天忘,后天搞混大后天重看手册(玩笑话),但是这种情况可以说每个人都…

[ai笔记3] ai春晚观后感-谈谈ai与艺术

欢迎来到文思源想的ai空间&#xff0c;这是技术老兵重学ai以及成长思考的第3篇分享&#xff01; 今天我们不聊技术&#xff0c;只聊感受&#xff01; 1 关于ai春晚 期待许久的ai春晚&#xff0c;但是等初一晚上观看的时候&#xff0c;或多或少还是有些失望。 首先是观看人数…

工业以太网交换机引领现代工厂自动化新潮流

随着科技的飞速发展&#xff0c;现代工厂正迎来一场前所未有的自动化变革&#xff0c;而工业以太网交换机的崭新角色正是这场变革的关键组成部分。本文将深入探讨工业以太网交换机与现代工厂自动化的紧密集成&#xff0c;探讨这一集成如何推动工业生产的智能化、效率提升以及未…

车载电子电器架构 —— 电子电气系统功能开发

车载电子电器架构 —— 电子电气系统功能开发 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再挣扎,出门靠自己,四海皆…

腾讯云4核8G服务器可以用来干嘛?怎么收费?

腾讯云4核8G服务器适合做什么&#xff1f;搭建网站博客、企业官网、小程序、小游戏后端服务器、电商应用、云盘和图床等均可以&#xff0c;腾讯云4核8G服务器可以选择轻量应用服务器4核8G12M或云服务器CVM&#xff0c;轻量服务器和标准型CVM服务器性能是差不多的&#xff0c;轻…

[缓存] - Redis

0.为什么要使用缓存&#xff1f; 用缓存&#xff0c;主要有两个用途&#xff1a;高性能、高并发。 1. 高性能 尽量使用短key 不要存过大的数据 避免使用keys *&#xff1a;使用SCAN,来代替 在存到Redis之前压缩数据 设置 key 有效期 选择回收策略(maxmemory-policy) 减…

汽车零部件制造业MES系统解决方案

一、​汽车零部件行业现状 随着全球汽车产业不断升级&#xff0c;汽车零部件市场竞争日趋激烈&#xff0c;从上游的钢铁、塑料、橡胶等生产到下游的主机厂配套制造&#xff0c;均已成为全球各国汽车制造大佬战略目标调整的焦点&#xff0c;其意欲在汽车零部件行业快速开疆扩土&…

【C语言】C的整理记录

前言 该笔记是建立在已经系统学习过C语言的基础上&#xff0c;笔者对C语言的知识和注意事项进行整理记录&#xff0c;便于后期查阅&#xff0c;反复琢磨。C语言是一种面向过程的编程语言。 原想在此阐述一下C语言的作用&#xff0c;然而发觉这些是编程语言所共通的作用&#…

【服务器数据恢复】服务器RAID模块硬件损坏的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 某品牌服务器中有一组由数块SAS硬盘组建的RAID5磁盘阵列&#xff0c;服务器操作系统是WINDOWS SERVER&#xff0c;服务器中存放企业数据&#xff0c;无数据库文件。 服务器出故障之前出现过几次意外断电的情况&#xff0c;服务器断电…

用云手机打造tiktok账号需要注意些什么?

随着tiktok平台的火热&#xff0c;越来越多的商家开始尝试更高效的tiktok运营方法。其中&#xff0c;tiktok云手机作为一种新科技引起了很多人的注意&#xff0c;那么用云手机运营tiktok需要注意些什么&#xff1f;下文将对此进行详细解析。 1. 不是所有的云手机都适合做tiktok…

[BeginCTF]真龙之力

安装程序 双击安装 出现了安装失败的标签&#xff0c;开发者不允许测试。 查看Mainfest入口文件 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android" android:versionCo…

【数据分享】1929-2023年全球站点的逐年平均能见度(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 之前我们分享过1929-2023年全球气象站点的逐年平均气温数据、逐年最高气温数据…

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

23考研已经落幕&#xff0c;我也成功的上岸华工&#xff0c;回首这一年多的历程&#xff0c;也是有一些经验想和大家分享一下。 首先说一下个人情况&#xff0c;本科211&#xff0c;初试成绩400分。专业课140。 整体时间安排 对于考研&#xff0c;很重要的一环就是时间安排&…

零基础学Python之整合MySQL

Python 标准数据库接口为 Python DB-API&#xff0c;Python DB-API为开发人员提供了数据库应用编程接口。 不同的数据库你需要下载不同的DB API模块&#xff0c;例如你需要访问Oracle数据库和Mysql数据&#xff0c;你需要下载Oracle和MySQL数据库模块。 DB-API 是一个规范. 它…

导数的几何意义【高数笔记】

1. 高数中的导数几何意义&#xff0c;与中学中斜率的联系 2. 导函数与导数的区别和联系又是什么 3. 导数的几何意义的题型是什么 4. 这些题型又有哪些区别 5. 点在曲线外和点在曲线上&#xff0c;需要注意什么 6. 法线和切线有什么关系 7. 法线是什么

EasyExcel分页上传数据

EasyExcel分页上传数据 一、实例 controller上传入口 PostMapping("/upload")ResponseBodyLog(title "导入工单", businessType BusinessType.IMPORT)public AjaxResult uploadFile(HttpServletRequest request, MultipartFile files) throws Exceptio…

java之Maven

1. maven Maven是管理和构建java项目的工具 项目依赖资源(jar包)的管理,避免版本冲突统一项目结构项目构建&#xff0c;标准跨平台(Linux,window,MacOS)的自动化项目管理 2.maven依赖仓库 2.maven安装 maven安装视频教程 3. IDEA集成Maven 4. maven的依赖范围 5. maven生命…