数据结构——链表(练习题)

大家好,我是小锋我们继续来学习链表。

我们在上一节已经把链表中的单链表讲解完了,大家感觉怎么样我们今天来带大家做一些练习帮助大家巩固所学内容。

1. 删除链表中等于给定值 val 的所有结点

. - 力扣(LeetCode)

我们大家来分析一下这个题,我们能想到的思路有两种,1,删除 2,插入

第一种,我们直接一个一个找当找到val我们就删除,然后继续重复下去。

第二种,我们创建一个新的头节点并沿着原节点一个一个走下去如果不是val我们就在新的头节点尾插。

第一种

#include<stdlib.h>struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* ps = head;while (ps){if (ps->val == val){head = head->next;ps->next = NULL;ps = head;}else{struct ListNode* pt = ps->next;if (pt) {if (pt->val == val){ps->next = pt->next;pt->next = NULL;}else{ps = ps->next;}}else {ps = ps->next;}}}return head;}

第二种

#include<stdlib.h>struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* pt=NULL;struct ListNode* ps=NULL;struct ListNode* cur=head;while(cur){if(cur->val==val){cur=cur->next;}else{if(ps){pt->next=cur;cur=cur->next;pt=pt->next;pt->next=NULL;}else{ps=cur;cur=cur->next;ps->next=NULL;pt=ps;}}}return ps;}

反转一个单链表

. - 力扣(LeetCode)

我们大家来分析这道题,有很多种思路这里我向大家推荐两种

1,我们将链表的朝向改变让最后一个节点变成表头,然后依次改变每个节点的指向就完成了反转

2,我们找到最后一个节点然后依次将每个节点尾插。

第一种

# include<stdio.h>
struct ListNode* reverseList(struct ListNode* head) {struct ListNode*ps=head;if(ps){struct ListNode*pt=ps->next;while(pt){struct ListNode*cur=pt->next;if(ps==head){pt->next=ps;ps->next=NULL;ps=pt;pt=cur;}else{pt->next=ps;ps=pt;pt=cur;}}}else{return NULL;}return ps;
}

第二种

# include<stdio.h>
struct ListNode* reverseList(struct ListNode* head) {struct ListNode*ps=NULL;struct ListNode*cur=head;struct ListNode*pt=NULL;struct ListNode*tall=NULL;if(cur){while(cur){if(cur->next){while(cur->next->next){cur=cur->next;}tall=cur;cur=cur->next;tall->next=NULL;}else{head=NULL;}if(ps){pt->next=cur;pt=pt->next;}else{ps=cur;pt=ps;}cur=head;}}else{return NULL;}return ps;
}

返回链表的中间结点

. - 力扣(LeetCode)

这一道题的思路也有很多,我们这里主要用快慢指针的思路来解决

我们创建两个指针,都指向头节点,然后一个指针一次走两步,一个指针一次走一步当快的指针走到最后一个节点是慢的指针刚好走到中间节点。

struct ListNode* middleNode(struct ListNode* head) {struct ListNode*quick=head;struct ListNode*slow=head;if(head){while(quick&&quick->next){quick=quick->next->next;slow=slow->next;   }}else{return NULL;}return slow;
}

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

这道题的思路在头节点定义两个指针先让一个指针先走k个然后再一起走当其中一个指针走到链表末尾时另一个指针就在倒数第k个。

typedef struct ListNode ListNode;struct ListNode {int val;struct ListNode *next;};struct ListNode* middleNode(int k, struct ListNode* head) {struct ListNode* ps = head;struct ListNode* pt = head;if (head) {while (k) {if (ps) {ps = ps->next;}else {break;}k--;}while (ps) {ps = ps->next;pt = pt->next;}}else {return NULL;}if (k<=0) {return pt;}else {return NULL;}}

下面这个是测试函数

int main() {ListNode* n1 = (ListNode*)malloc(sizeof(ListNode));assert(n1);ListNode* n2 = (ListNode*)malloc(sizeof(ListNode));assert(n2);ListNode* n3 = (ListNode*)malloc(sizeof(ListNode));assert(n3);ListNode* n4 = (ListNode*)malloc(sizeof(ListNode));assert(n4);ListNode* n5 = (ListNode*)malloc(sizeof(ListNode));assert(n5);n1->val = 1;n2->val = 2;n3->val = 3;n4->val = 4;n5->val = 5;n1->next = n2;n2->next = n3;n3->next = n4;n4->next = n5;n5->next = NULL;ListNode* add= middleNode(6,NULL);if (add)printf("%d", add->val);elseprintf("NULL");return 0;
}

有序链表合并

. - 力扣(LeetCode)

这道题的解题思路

创建一个新的头节点然后建立两个指针分别指向两个升序链表对比两个节点的val,选小的尾插选中的那个节点的指针指向下一个节点,最后还没有走完的指针将全部节点都尾插。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {struct ListNode*ps=NULL;struct ListNode*cur=NULL;if(list1==NULL)return list2;if(list2==NULL)return list1;while(list1&&list2){if(list1->val>list2->val){if(ps){cur->next=list2;cur=cur->next;list2=list2->next;}else{ps=list2;cur=ps;list2=list2->next;}}else{if(ps){cur->next=list1;cur=cur->next;list1=list1->next;}else{ps=list1;cur=ps;list1=list1->next;}}}if(list1){cur->next=list1;}else{cur->next=list2;}return ps;
}

链表分割

这一道题我想的思路是创建一个头节点,把小于x的节点在原链表中删除后尾插该节点,然后在把该链表与原链表连接。

但是还有一种更好的方法,我们直接创建两个头节点分别尾插大于x和小于x的节点最后再连接。

无疑这一种方法更为简单。

我们来试试

/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:ListNode* partition(ListNode* pHead, int x) {ListNode*ps,*pt,*psd,*ptd;psd=ps=(ListNode*)malloc(sizeof(int)+sizeof(ListNode*));ptd=pt=(ListNode*)malloc(sizeof(int)+sizeof(ListNode*));ListNode*cur=pHead;while(cur){if(cur->val<x){psd->next=cur;psd=cur;}else{ptd->next=cur;ptd=cur;}cur=cur->next;}psd->next=pt->next;ptd->next=NULL;pHead=ps->next;free(ps);free(pt);return pHead;}
};

链表的回文结构

这一道题我们可以找到链表的中间节点把中间节点后面的反转然后从头与尾向中间比较如果都一样那么就是回文结构了。

/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:bool chkPalindrome(ListNode* A) {ListNode*ps=A;ListNode*pt=A;while(ps&&ps->next){ps=ps->next->next;pt=pt->next;}ListNode*cur=pt;ListNode*list=cur->next;ListNode*add=list->next;while(list){list->next=cur;cur=list;list=add;if(add)add=add->next;}pt->next=NULL;ListNode*are=A;while(cur){if(are->val!=cur->val){return false;}else{are=are->next;cur=cur->next;}}return true;}
};

相交链表

这道题我们的思路是分别找出长的链表与短的链表节点个数然后用长的节点数减去短的节点数得到的数就是长的链表比短的链表多出的节点个数然后创建两个指针long,short,long先走多出的个数然后再一起走当long与short指向的next相等时就找到了相交节点。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {int a=0;int b=0;int n=0;struct ListNode *cut=headA;while(cut->next){a++;cut=cut->next;}cut=headB;while(cut->next){b++;cut=cut->next;}struct ListNode *longg=headA;struct ListNode *shortt=headB;if(a<b){n=b-a;while(n--){shortt=shortt->next;}}else{n=a-b;while(n--){longg=longg->next;}}while(longg&&shortt){if(longg==shortt){return longg;}else{longg=longg->next;shortt=shortt->next;}}return NULL;
}

判断环形链表

让我们来看看这道题,我的思路是快慢指针,类似追击问题,我们创建两个指针一个指针以一次两个节点的速度走下去,一个指针一次一个节点走下去,如果是有环的链表那么指针一定会相交,如果不是环形链表那么快的会遇到NULL。

bool hasCycle(struct ListNode *head) {struct ListNode *quick=head;struct ListNode *siow=head;while(quick&&quick->next){quick=quick->next->next;siow=siow->next;if(quick==siow){return true;}}return false;  
}

找环形链表入口

先说一个结论:

让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环
运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇
这样看这道题是不是清晰明了
struct ListNode *detectCycle(struct ListNode *head) {struct ListNode *quick=head;struct ListNode *siow=head;while(quick&&quick->next){quick=quick->next->next;siow=siow->next;if(quick==siow){struct ListNode *ps=head;while(quick!=ps){quick=quick->next;ps=ps->next;}return ps;}}return NULL;
}

接下来大家思考几个问题

快指针一次走 3 步,走 4 步, ...n 步行吗?

  以上就是全部内容了,如果有错误或者不足的地方欢迎大家给予建议。 

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

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

相关文章

网站为什么要选择使用安全加速SCDN?

安全加速SCDN&#xff08;安全内容交付网络&#xff09;是一种网络加速服务&#xff0c;旨在提高网站和应用程序的性能和安全性。它使用专门的技术和基础设施来加速内容传输并保护网站免受网络攻击。 安全加速SCDN可以通过内容缓存、快速传输和动态路由技术来加速网站和应用程…

SpringMVC第一个helloword项目

文章目录 前言一、SpringMVC是什么&#xff1f;二、使用步骤1.引入库2.创建控制层3.创建springmvc.xml4.配置web.xml文件5.编写视图页面 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; SpringMVC 提示&#xff1a;以下是本篇文章正文内容&#xf…

【ML】类神经网络训练不起来怎么办 5

【ML】类神经网络训练不起来怎么办 5 1. Saddle Point V.S. Local Minima(局部最小值 与 鞍点)2. Tips for training: Batch and Momentum(批次与 动量)2.1 Tips for training: Batch and Momentum2.2 参考文献:2.3 Gradient Descent2.4 Concluding Remarks(前面三讲)3.…

C# OpenCvSharp 轮廓检测

目录 效果 代码 下载 效果 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using OpenCvSharp; using OpenCvSharp.…

Git 命令总览

Git Git 是一个版本控制系统&#xff0c;用于管理项目代码。通过 Git 可以轻松地进行代码的提交、更新和合并&#xff0c;确保项目代码的安全性和稳定性。同时&#xff0c;Git 还提供了丰富的工具和功能&#xff0c;如分支管理、代码审查、版本回退等&#xff0c;帮助开发更好…

大模型 智能体 智能玩具 智能音箱 构建教程 wukong-robot

视频演示 10:27 一、背景 继上文《ChatGPT+小爱音响能擦出什么火花?》可以看出大伙对AI+硬件的结合十分感兴趣,但上文是针对市场智能音响的AI植入,底层是通过轮询拦截,算是hack兼容,虽然官方有提供开发者接口,也免不了有许多局限性(比如得通过特定指令唤醒),不利于我…

【Web应用技术基础】CSS(6)——使用 HTML/CSS 实现 Educoder 顶部导航栏

第一题&#xff1a;使用flex布局实现Educoder顶部导航栏容器布局 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Educoder</title><script src"https://cdn.staticfile.org/jquery/1.1…

C/C++语言学习路线: 嵌入式开发、底层软件、操作系统方向(持续更新)

初级&#xff1a;用好手上的锤子 1 【感性】认识 C 系编程语言开发调试过程 1.1 视频教程点到为止 1.2 炫技视频看看就行 1.3 编程游戏不玩也罢 有些游戏的主题任务就是编程&#xff0c;游戏和实际应用环境有一定差异&#xff08;工具、操作流程&#xff09;&#xff0c;在…

Unity AI Navigation自动寻路

目录 前言一、Unity中AI Navigation是什么&#xff1f;二、使用步骤1.安装AI Navigation2.创建模型和材质3.编写向目标移动的脚本4.NavMeshLink桥接组件5.NavMeshObstacle组件6.NavMeshModifler组件 三、效果总结 前言 Unity是一款强大的游戏开发引擎&#xff0c;而人工智能&a…

ssm网上订餐管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目采用线性算法

一、源码特点 ssm 网上订餐管理系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模…

移动端开发思考:Uniapp的上位替代选择

文章目录 前言跨平台开发技术需求技术选型uniappFlutterMAUIAvalonia安卓原生 Flutter开发尝试Avalonia开发测试测试项目新建项目代码MainViewMainViewModel 发布/存档 MAUI实战&#xff0c;简单略过打包和Avalonia差不多 总结 前言 作为C# .NET程序员&#xff0c;我有一些移动…

C++优先队列——priority_queue,函数对象,labmda表达式,pair等

头文件&#xff1a;#include<queue> 内部使用堆来实现&#xff0c;在需要或得最大的几个值或最小的几个值而不关心整个数组的顺序时非常好用。 用法&#xff1a; priority_queue<int, vector<int>, greater<int>>q; 第一个参数为堆中存储的元素。 …

Jmeter调用测试片段 —— 模块控制器

可以使用模块控制器调用测试片段。模块控制器提供了一种在运行时将测试片段替换为当前测试计划的机制。测试片段可以位于任何线程组中。 1、打开一个Jmeter窗口&#xff0c;添加好线程组、用户定义变量、模块控制器、测试片段、察看结果树。 2、用户定义变量同样定义好访问ip及…

linux离线安装jenkins及使用教程

本教程采用jenkins.war的方式离线安装部署&#xff0c;在线下载的方式会遇到诸多问题&#xff0c;不宜采用 一、下载地址 地址&#xff1a;Jenkins download and deployment 下载最新的长期支持版 由于jenkins使用java开发的&#xff0c;所以需要安装的linux服务器装有jdk环…

对话 Mines of Dalarnia: Web3 游戏创新,社区驱动与公链共建

作者&#xff1a;stellafootprint.network 嘉宾&#xff1a;Manfred Pack&#xff0c;Mines of Dalarnia 游戏开发总监 采访者&#xff1a;Alex Cooper&#xff0c;Footprint Analytics 北美社区与 BD 负责人 在区块链游戏领域&#xff0c;去中心化和玩家经济正在颠覆传统游戏…

3D模型格式转换案例 | CDM Tech如何应用HOOPS Exchange提升AR产品性能?

自2016年成立以来&#xff0c;CDM Tech一直致力于为汽车行业设计度量产品和提供其他解决方案&#xff0c;以满足主要的德国本土汽车制造巨头的需求。然而&#xff0c;随着时间的推移&#xff0c;他们开始将目光转向增强现实&#xff08;AR&#xff09;技术&#xff0c;并最终将…

【C语言】宏定义

1. 预定义符号 C语言设置了一些预定符号&#xff0c;可以直接使用&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编译的时间 __STDC__ //如果编译器遵循ANSI C&…

Convex and Semi-Nonnegative Matrix Factorizations

我们提出了非负矩阵分解&#xff08;NMF&#xff09;主题的几种新变体。考虑形式为X FG^T的因子分解&#xff0c;我们关注的是G被限制为包含非负元素的算法&#xff0c;但允许数据矩阵X具有混合符号&#xff0c;从而扩展了NMF方法的适用范围。我们还考虑了基向量F被约束为数据…

电脑突然死机怎么办?

死机是电脑常见的故障问题&#xff0c;尤其是对于老式电脑来说&#xff0c;一言不合电脑画面就静止了&#xff0c;最后只能强制关机重启。那么你一定想知道是什么原因造成的吧&#xff0c;一般散热不良最容易让电脑死机&#xff0c;还有系统故障&#xff0c;比如不小心误删了系…

Mini-Gemini: Mining the Potential of Multi-modality Vision Language Models

Mini-Gemini: Mining the Potential of Multi-modality Vision Language Models 相关链接&#xff1a;arxiv 关键字&#xff1a;Vision Language Models、Multi-modality、High-Resolution Visual Tokens、High-Quality Data、VLM-guided Generation 摘要 在这项工作中&#x…