leetcode每日一练:链表OJ题

链表经典算法OJ题

1.1 移除链表元素

题目要求:

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == 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
输出:[]

解题思路:

思路1:

定义两个指针,一个指向当前节点,一个指向当前节点的下一个节点,如果下一个节点是要删除的节点就将当前节点的next存储下一个节点的再下一个节点的地址,然后free那个节点。知道遍历完原链表,该思路是改变原链表。

思路2:

建立一个新的链表,遍历原链表,将原链表中的非删除节点给新的链表,遍历结束后新链表中没有要删除节点。

struct ListNode{int val;struct ListNode *next;
};
struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* Newhead, * NewTail;//一个头链表,一个链表尾部Newhead = NewTail = NULL;//遍历原链表struct ListNode* pcur = head;while (pcur){if (pcur->val != val){if (Newhead == NULL){Newhead = NewTail = pcur;}else{NewTail->next = pcur;NewTail = NewTail->next;}}pcur = pcur->next;}//如果要删除值在原链表为节点,新链表的尾节点就不会指向NULL,所以这里要判断if (NewTail){NewTail->next = NULL;}return Newhead;
}

1.2 反转链表

题目要求:

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

解题思路:

可以定义三个新的节点类型的指针变量n1、n2、n3。然后就可以使用这三个指针来反转链表。首先n1初始化为NULL,n2初始化为head链表头结点,n3则是head头结点的下一个节点。然后循环n2->next = n1, n1 = n2, n2 = n3,n3 = n3->next。循环往复就完成了反转链表的操作。

typedef struct ListNode{int val;struct ListNode *next;
}*pList;//反转链表函数实现
pList reverselist(pList head){if (head == NULL){return NULL;}pList n1, n2, n3;n1 = NULL, n2 = head, n3 = head->next;while (n2){n2->next = n1;n1 = n2;n2 = n3;if(n3)//如果n3为NULL就不再向后访问了n3 = n3->next;}return n1;
}//以下调用上面函数的main是我自己写的,可以供大家参考
int main()
{//创建链表struct ListNode* phead, *pTail, *p;phead = pTail = NULL;int n = 0;printf("请输入要创建链表节点个数:>");scanf("%d", &n);int i = 0;for (i = 0; i < n; i++){p = (pList)malloc(sizeof(struct ListNode));printf("请输入第%d个节点的值:>", i + 1);scanf("%d", &(p->val));p->next = NULL;if (phead == NULL){phead = p;pTail = phead;}else{pTail->next = p;pTail = pTail->next;}}//调用反转链表函数pList Newhead = reverselist(phead);if (Newhead == NULL){perror("reverselist");return;}phead = Newhead;//打印链表节点数据while (Newhead){printf("%d->", Newhead->val);Newhead = Newhead->next;}printf("NULL\n");i = 1;Newhead = phead;//销毁链表while (Newhead){phead = phead->next;free(Newhead);Newhead = phead;printf("已释放第%d条节点\n", i);i++;}return 0;
}

1.3 合并两个有序链表

题目要求:

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

解题思路:

定义两个新的节点指针,一个头节点,一个尾结点。比较两个原链表当前节点的数据大小,然后插入新的链表,知道插完为止

typedef struct ListNode {int val;struct ListNode* next;
}*pList;
//合并两个有序链表函数实现
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if (list1 == NULL){return list2;}if (list2 == NULL){return list1;}struct ListNode* cur1, *cur2;cur1 = list1, cur2 = list2;struct ListNode* phead, * pTail;phead = pTail = (struct ListNode*)malloc(sizeof(struct ListNode));while (cur1 && cur2) {if (cur1->val < cur2->val){pTail->next = cur1;pTail = pTail->next;cur1 = cur1->next;}else{pTail->next = cur2;pTail = pTail->next;cur2 = cur2->next;}}if (cur1) {pTail->next = cur1;}if (cur2) {pTail->next = cur2;}struct ListNode* retList = phead->next;free(phead);return retList;
}
//以下创建链表调用函数的代码是自己写的,只为调用上面函数,不是链表规范创建。仅供参考
int main()
{struct ListNode* phead1, pTail1, p1;struct ListNode* phead2, pTail2, p2;phead1 = pTail1 = NULL;phead2 = pTail2 = NULL;int n = 0;printf("请输入要创建p1和p2链表节点个数:>");scanf("%d", &n);int i = 0;for (i = 0; i < n; i++){p1 = (pList)malloc(sizeof(struct ListNode));p2 = (pList)malloc(sizeof(struct ListNode));printf("请输入p1链表第%d个节点的值:>", i + 1);scanf("%d", &(p1->val));printf("请输入p2链表第%d个节点的值:>", i + 1);scanf("%d", &(p2->val));p1->next = NULL;p2->next = NULL;if (phead1 == NULL && phead2 == NULL){phead1 = p1;pTail1 = phead1;phead2 = p2;pTail2 = phead2;}else{pTail1->next = p1;pTail1 = pTail1->next;pTail2->next = p2;pTail2 = pTail2->next;}}pList Newhead = mergeTwoLists(phead1,phead2);if (Newhead == NULL){perror("reverselist");return;}pList phead = Newhead;while (Newhead){printf("%d->", Newhead->val);Newhead = Newhead->next;}printf("NULL\n");i = 1;Newhead = phead;while (Newhead){phead = phead->next;free(Newhead);Newhead = phead;printf("已释放第%d条节点\n", i);i++;}return 0;
}

1.4 链表的中间节点

题目要求:

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:head = [1,2,3,4,5]
输出:[3,4,5]
解释:链表只有一个中间结点,值为 3 。

示例 2:

输入:head = [1,2,3,4,5,6]
输出:[4,5,6]
解释:该链表有两个中间结点,值分别为 3 和 4 ,返回第二个结点。

解题思路:

快慢指针:使用快慢指针来遍历链表,慢指针每次走一步,快指针每次走两步,当快指针走到最后慢指针刚好走到中间节点。因为快指针是慢指针的2倍。所以快指针从起点到终点时慢指针就是这个路程的一半,是中点。

typedef struct ListNode{int val;struct ListNode* next;
}*pList;
//函数实现
struct ListNode* middleNode(struct ListNode* head) {if (head == NULL){return NULL;}struct ListNode* slow, *fast;slow = fast = head;//节点数可能是奇数个也可能是偶数个,所以要两种判断while (fast && fast->next) {slow = slow->next;fast = fast->next->next;}return slow;
}

1.5 环形链表的约瑟夫问题

著名的Josephus问题

据说著名的历史学家 Josephus有过以下的故事:故事据说发生在古罗马时期,在罗马人占领乔塔帕特后,39个犹太人与约瑟夫及他的朋友躲到一个洞中,他们宁愿死也不要被敌人抓到,于是约定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下1个人重新报数,直到所有人都自杀身亡为止。

然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

题目要求:

编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。

下一个人继续从 1 开始报数。

n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?

数据范围: 1≤𝑛,𝑚≤100001≤n,m≤10000

进阶:空间复杂度 𝑂(1)O(1),时间复杂度 𝑂(𝑛)O(n)

示例1

输入:

5,2     

复制返回值:

3    

复制说明:

开始5个人 1,2,3,4,5 ,从1开始报数,1->1,2->2编号为2的人离开
1,3,4,5,从3开始报数,3->1,4->2编号为4的人离开
1,3,5,从5开始报数,5->1,1->2编号为1的人离开
3,5,从3开始报数,3->1,5->2编号为5的人离开
最后留下人的编号是3      

示例2

输入:

1,1

返回值:

1
typedef struct ListNode ListNode;创建一个节点并返回
ListNode* ListBuyNode(int val)
{ListNode* ret = (ListNode*)malloc(sizeof(ListNode));if(ret==NULL){perror("malloc");return NULL;}ret->val = val;ret->next = NULL;return ret;
}
//创建一个环形链表并返回
ListNode* CreatNode(int n)
{ListNode* phead = ListBuyNode(1);ListNode* pTail = phead;int i = 0;for(i=2;i<=n;i++){pTail->next = ListBuyNode(i);pTail = pTail->next;}pTail->next = phead;//将链表循环return pTail;
}int ysf(int n, int m ) {// write code hereListNode* prev = CreatNode(n);ListNode* cur = prev->next;int count = 1;//遍历判断while(cur->next!=cur){if(count == m){prev->next = cur->next;free(cur);cur = prev->next;count = 1;}else{prev = cur;cur = cur->next;count++;}}return cur->val;
}

1.6 分隔链表

题目要求:

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

示例 1:

输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

示例 2:

输入:head = [2,1], x = 2
输出:[1,2]

解题思路:

大小链表:我们可以创建两个新的链表,为大小链表。遍历原链表。大于等于x的节点连接在大链表,小于x的节点连接在小链表。最后将大链表的头结点连接在小链表的尾结点。返回小链表的头结点

typedef struct ListNode {int val;struct ListNode* next;
}*pList;//分隔链表的函数实现
struct ListNode* partition(struct ListNode* head, int x) {if (head == NULL){return NULL;}struct ListNode* lessHead, * lessTail;struct ListNode* greaterHead, * greaterTail;//定义哨兵位lessHead = lessTail = (struct ListNode*)malloc(sizeof(struct ListNode));greaterHead = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* pcur = head;//用来遍历原链表//分隔操作while (pcur){if (pcur->val >= x){greaterTail->next = pcur;greaterTail = greaterTail->next;}else{lessTail->next = pcur;lessTail = lessTail->next;}pcur = pcur->next;}//将大小链表连接起来lessTail->next = greaterHead->next;if(greaterTail)greaterTail->next = NULL;//释放哨兵位free(greaterHead);struct ListNode* retList = lessHead->next;free(lessHead);//返回头结点return retList;
}
int main()
{pList phead, pTail, p;phead = pTail = NULL;int n = 0;printf("请输入要创建链表节点个数:>");scanf("%d", &n);int i = 0;for (i = 0; i < n; i++){p = (pList)malloc(sizeof(struct ListNode));printf("请输入第%d个节点的值:>", i + 1);scanf("%d", &(p->val));p->next = NULL;if (phead == NULL){phead = p;pTail = phead;}else{pTail->next = p;pTail = pTail->next;}}pList Newhead = partition(phead, 3);if (Newhead == NULL){perror("reverselist");return;}phead = Newhead;while (Newhead){printf("%d->", Newhead->val);Newhead = Newhead->next;}printf("NULL\n");i = 1;Newhead = phead;while (Newhead){phead = phead->next;free(Newhead);Newhead = phead;printf("已释放第%d条节点\n", i);i++;}return 0;
}

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

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

相关文章

模电-二极管及其应用51单片机LED点亮前置工作!

今日小记 2024-7-2&#xff0c;星期二&#xff0c;16:32&#xff0c;天气&#xff1a;晴&#xff0c;心情&#xff1a;晴。持续了两个星期的梅雨天终于暂时过去啦&#xff0c;迎来了久违的阳光&#xff0c;虽然没有雨天凉快&#xff0c;但是能看到太阳也是开心哒&#xff0c;心…

2021强网杯

一、环境 网上自己找 二、步骤 2.1抛出引题 在这个代码中我们反序列&#xff0c;再序列化 <?php$raw O:1:"A":1:{s:1:"a";s:1:"b";};echo serialize(unserialize($raw));//O:1:"A":1:{s:1:"a";s:1:"b";…

工业 web4.0UI 风格品质卓越

工业 web4.0UI 风格品质卓越

单向链表结构

链表结构简介 链表结构是一种用比较特殊的数据结构类型&#xff0c;它也是线性数据结构中的一种&#xff0c;但是与栈结构等线性数据结构不同&#xff0c;它的内部结构并不是一个简单的存储空间&#xff0c;而是一个带有指向性质的单元。要理解链表结构要弄清楚两个问题&#x…

不要再被骗了!电脑无法进入系统的原因可能是这个硬件坏了而已……

前言 前段时间小白在抖音上发了很多很多很多的视频&#xff0c;其中应该是有很多商家关注了小白。 然后就会出现很多很多很多的赚钱小门道…… 电脑开机没有显示&#xff1f;换显卡&#xff01; 电脑还是不开机&#xff1f;换CPU 电脑还是一样不开机…… 经过了一番大折腾…

10.8K star!史上最强Web应用防火墙雷池WAF

长亭雷池SafeLine是长亭科技耗时近 10 年倾情打造的WAF(Web Application Firewall)&#xff0c; 一款敢打出口号 “不让黑客越雷池一步” 的 WAF&#xff0c;愿称之为史上最强的一款Web应用防火墙&#xff0c;足够简单、足够好用、足够强的免费且开源的 WAF&#xff0c;基于业…

pads layout 脚本导出不能运行excle解决办法

在一台新的电脑上安装好PADS&#xff0c;打开PCB文件导出坐标文件时&#xff1a; 出现“ActiveX Automation: server could not be found.”的问题,导致无法成功导出文件,错误提示截图如下&#xff1a; 导致上述问题的原因是在我们配置导出带坐标的脚本时,默认使用的是微软…

Java 实现application/x-www-form-urlencoded编码格式的POST请求

一、实现方式 在Java中&#xff0c;实现application/x-www-form-urlencoded内容类型通常涉及到发送HTTP POST请求。你可以使用java.net.HttpURLConnection或者第三方库如Apache HttpClient来实现。 以下是使用HttpURLConnection发送application/x-www-form-urlencoded数据的代…

昇思MindSpore学习笔记3--张量 Tensor

一、张量Tensor概念 矢量、标量和其他张量的计算函数&#xff0c;有内积、外积、线性映射以及笛卡儿积等 张量坐标在 n 维空间内&#xff0c;有 nr 个分量 每个分量都是坐标的函数,变换时每个坐标分量都按规则作线性变换 张量是一种特殊的数据结构&#xff0c;类似于数组和…

利用深度学习模型进行语音障碍自动评估

语音的产生涉及器官的复杂协调&#xff0c;因此&#xff0c;语音包含了有关身体各个方面的信息&#xff0c;从认知状态和心理状态到呼吸条件。近十年来&#xff0c;研究者致力于发现和利用语音生物标志物——即与特定疾病相关的语音特征&#xff0c;用于诊断。随着人工智能&…

js基础学习

1、js概述 js是javascript的简称&#xff0c;作用是实现页面和用户的交互 js由浏览器解析运行&#xff0c;不需要编译 js由es基础语法&#xff0c;bom浏览器相关&#xff0c;dom文档操作相关 三大部分组成 2、html引入js <!DOCTYPE html> <html lang"zh-CN&qu…

Vue项目打包上线

Nginx 是一个高性能的开源HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP代理服务器。它在设计上旨在处理高并发的请求&#xff0c;是一个轻量级、高效能的Web服务器和反向代理服务器&#xff0c;广泛用于提供静态资源、负载均衡、反向代理等功能。 1、下载nginx 2、…

k8s学习--k8s群集ELK日志收集部署最详细的过程与应用(收集k8s群集日志)(图形化界面手把手教学)

文章目录 FilebeatFilebeat主要特点Filebeat使用场景 ELK简介Elasticsearch简介Elasticsearch主要特点Elasticsearch使用场景 Logstash简介Logstash主要特点Logstash使用场景 Kibana简介Kibana主要特点Kibana使用场景 简单理解 环境一、ELK集群部署1.软件安装2.软件配置及启动(…

Webpack: Loader开发 (2)

概述 在上一篇文章中&#xff0c;我们已经详细了解了开发 Webpack Loader 需要用到的基本技能&#xff0c;包括&#xff1a;Loader 基本形态、如何构建测试环境、如何使用 Loader Context 接口等。接下来我们继续拓展学习一些 Loader 辅助工具&#xff0c;包括&#xff1a; 了…

什么是自然语言处理(NLP)?详细解读文本分类、情感分析和机器翻译的核心技术

什么是自然语言处理&#xff1f; 自然语言处理&#xff08;Natural Language Processing&#xff0c;简称NLP&#xff09;是人工智能的一个重要分支&#xff0c;旨在让计算机理解、解释和生成人类的自然语言。打个比方&#xff0c;你和Siri对话&#xff0c;或使用谷歌翻译翻译一…

2024广州国际米粉产业展览会暨米粉节

2024广州国际米粉产业展览会 时间&#xff1a;2024年11月16-18日 地点&#xff1a;广州中国进出口商品交易会展馆 主办单位&#xff1a;企阳国际会展集团 【展会简介】 米粉作为一种历史悠久&#xff0c;人们日常食用的食物&#xff0c;其市场需求稳定&#xff0c;且随着人…

WSL2安装ContOS7并更新gcc

目录 WSL2安装CentOS7下载安装包安装启动CentOS7 CentOS7更换国内源gcc从源码安装gcc卸载gcc CMake中使用gcc关于linux配置文件参考 WSL2安装CentOS7 Windows11官方WSL2已经支持Ubuntu、Open SUSE、Debian。但是没有centos&#xff0c;所以centos的安装方式略有不同。 下载安…

家政小程序的开发:打造现代式便捷家庭服务

随着现代生活节奏的加快&#xff0c;人们越来越注重生活品质与便利性。在这样的背景下&#xff0c;家政服务市场迅速崛起&#xff0c;成为许多家庭日常生活中不可或缺的一部分。然而&#xff0c;传统的家政服务往往存在信息不对称、服务效率低下等问题。为了解决这些问题&#…

【D3.js in Action 3 精译】1.2.2 可缩放矢量图形(三)

当前内容所在位置 第一部分 D3.js 基础知识 第一章 D3.js 简介 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知 1.2.1 HTML 与 DOM1.2.2 SVG - 可缩放矢量图形 ✔️ 第一部分第二部分【第三部分】✔️ 1.2.3 Canvas 与 WebGL&#xff08;精译中 ⏳&#xff09;1.2.4 C…

独立站新风口:TikTok达人带货背后的双赢合作之道

TikTok以其庞大的用户基础、高度互动性和创新的内容形式&#xff0c;为独立站带来了前所未有的发展机遇。独立站与TikTok达人的合作&#xff0c;不仅能够帮助独立站快速提升品牌知名度和销售额&#xff0c;还能为TikTok达人带来更多商业机会和影响力。本文Nox聚星将和大家探讨独…