当前位置: 首页 > news >正文

数据结构:链表经典算法OJ题

目录

前言

一、移除链表元素

二、反转链表

三、合并两个有序链表

四、链表的中间节点

五、环形链表的约瑟夫问题


前言

    在了解了链表的相关知识后,我们还需要一些题目进行练习加深对链表这方面知识的理解,也可以用来检测链表这块学的的怎么样,废话不多说,开始上手。

一、移除链表元素

    这里给上题目链接感兴趣的可以看一下(移除链表元素),

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回新的头节点 。

 看题目描述,我们需要删除链表中链表节点为特定值的节点。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode*a=NULL;struct ListNode*b=NULL;if(head==NULL)return head;while(head){if(head->val!=val){if(a==NULL)a=b=head;else{b->next=head;b=b->next;}}head=head->next;}if(b)b->next=NULL;return a;
}

    首先,如果链表本身为空,就可以直接返回一个空指针,如果不为空就可以开始下一个阶段,先创建两个指针a,b指向开始给的头结点,让初始头结点开始遍历,如果遇到节点值为特定值就让b节点指向初始头结点的下一个,相当于跳过了这个节点,最后遍历完,如果b节点不为空,就将b的下一个节点置空,相当于是把那些带有特定值的节点删除了。

二、反转链表

    这里先给上题目链接(反转链表)

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

这里先给上代码,慢慢来讲解一下。 

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* reverseList(struct ListNode* head) {if(head==NULL)return head;struct ListNode*n1=NULL;struct ListNode*n2=head;struct ListNode*n3=head->next;while(n2){n2->next=n1;n1=n2;n2=n3;if(n3)n3=n3->next;}return n1;
}

     首先还是要判断链表是否为空,空链表直接返回就行了,这里需要创建三个指针,在遍历链表时,将当前节点的 next 指针改为指向前一个节点,由于节点没有引用其前一个节点,因此必须事先存储其前一个节点,在更改引用之前,还需要存储后一个节点,最后返回新的头引用。

三、合并两个有序链表

    题目链接(合并有序链表)

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

这道题让我们把两个有序链表合并在一起并且合并后的链表依然有序,这里先上代码,后面讲解。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if(list1==NULL)return list2;if(list2==NULL)return list1;struct ListNode*n1=(struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode*n2=n1;while(list1&&list2){if(list1->val<=list2->val){n2->next=list1;list1=list1->next;n2=n2->next;}else{n2->next=list2;list2=list2->next;n2=n2->next;}}if(list1)n2->next=list1;if(list2)n2->next=list2;struct ListNode*c=n1->next;free(n1);n1=NULL;return c;
}

 首先判断两个有序链表中是否有空链表,如果有一方为空链表,就可以直接返回另一个链表了,需要开辟一个新的链表,将两个链表的每一个值一一比较排个序,再一个一个的放入新的链表当中。

四、链表的中间节点

    题目链接(链表的中间节点)

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

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

 这道题可以用很多种方式写出来,这里用的是快慢指针的方式,还有计数器法等方式(计数器法就是先遍历一遍链表算出有多少个节点,再除以二,按照除后的数字在遍历一遍到中间节点位子),这里快慢指针法就先上代码,后面讲解。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* middleNode(struct ListNode* head) {struct ListNode*a=head;int i=0;while(head){head=head->next;i++;}int count=i/2;while(count>0){a=a->next;count--;}return a;
}

让俩个指针开始时同时指向头结点,一个一次走一步,一个每次走两步,在快指针到达尾节点或者空节点时(奇数节点链表和偶数节点链表会不一样),慢指针就会在中间节点的位置(奇数节点指针会在中间节点,偶数节点指针会在中间两个节点的后一个节点),最后输出慢指针就行了。

五、环形链表的约瑟夫问题

     题目链接(约瑟夫问题)

描述

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

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

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 

 先上代码,后面慢慢讲解。

#include<stdlib.h>#include<stdio.h>
typedef struct music
{int data;struct music* next;
}music;
music*initial(int n)
{music*a=(music*)malloc(sizeof(music));a->data=n;a->next=NULL;return a;
}
music*creat(int n)
{music*a=initial(1);music*b=a;for(int i=2;i<=n;i++){b->next=initial(i);b=b->next;}b->next=a;return b;
}
int ysf(int n, int m ) {music*a=creat(n);music*head=a->next;int count=1;while(head->next!=head){if(count==m){a->next=head->next;free(head);head=a->next;count=1;}else{a=head;head=head->next;count++;}}return head->data;
}

    这道题涉及到了链表的创建,所以就需要一个包含数据成员的结构体以及初始化函数和创建链表相关函数,在实现约瑟夫问题的函数中,先创建head和a指针,head指针就是扮演着正在报数的那个人,a这是head的前一个节点,当报数的head报道特定的数字,a就会跳过这个节点,然后再把这个节点释放掉,head继续在a->next,循环着操作,留下最后一个就可以输出结果了。


    本篇内容就到这里了,没到题目都给了链接,可以自己去尝试解题,光听的话效果没那么好。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Linux】权限理解
  • Python的lambda函数
  • dockerfile之vllm大模型镜像构建
  • Go语言加Vue3零基础入门全栈班10 Go语言+gRPC用户微服务项目实战 2024年07月31日 课程笔记
  • Hugging Face下载模型
  • 技术详解:视频美颜SDK与直播美颜插件开发指南
  • XQuery 术语
  • 使用Spring Security实现Java应用的安全管理
  • 视频美颜SDK与直播插件的实现原理及优化方案详解
  • qt-声明
  • C语言菜鸟入门·数据结构·链表超详细解析
  • Google Earth Engine(GEE)——逐月筛选影像,并给影像集合添加新的属性
  • Vue3详细介绍,正则采集器所用前端框架
  • 代码随想录27期|Python|Day37|56.合并区间|738.单调递增的数字
  • SSM项目学习:用xml配置文件或注解开发实现控制反转和依赖注入
  • [PHP内核探索]PHP中的哈希表
  • 0基础学习移动端适配
  • 2019年如何成为全栈工程师?
  • eclipse的离线汉化
  • Java深入 - 深入理解Java集合
  • k个最大的数及变种小结
  • nginx 负载服务器优化
  • React Native移动开发实战-3-实现页面间的数据传递
  • Redash本地开发环境搭建
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • Vue小说阅读器(仿追书神器)
  • Web Storage相关
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 浅谈web中前端模板引擎的使用
  • 思维导图—你不知道的JavaScript中卷
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • 【干货分享】dos命令大全
  • 阿里云ACE认证学习知识点梳理
  • !!java web学习笔记(一到五)
  • # Java NIO(一)FileChannel
  • # 达梦数据库知识点
  • #APPINVENTOR学习记录
  • $.ajax()方法详解
  • (7)摄像机和云台
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (差分)胡桃爱原石
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (十八)Flink CEP 详解
  • (十二)Flink Table API
  • (四十一)大数据实战——spark的yarn模式生产环境部署
  • (循环依赖问题)学习spring的第九天
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (一)Thymeleaf用法——Thymeleaf简介
  • (转)负载均衡,回话保持,cookie