链表OJ题讲解2

💓博主个人主页:不是笨小孩👀
⏩专栏分类:数据结构与算法👀
🚚代码仓库:笨小孩的代码库👀
⏩社区:不是笨小孩👀
🌹欢迎大家三连关注,一起学习,一起进步!!💓

链表OJ

  • 链表的回文结构
  • 链表分割
  • 两个链表的交集
  • 链表循环
    • 思考
  • [链表周期 II](https://leetcode.cn/problems/linked-list-cycle-ii/description/)
    • 方法一
    • 方法二

在这里插入图片描述

链表的回文结构

在这里插入图片描述

回文节后是对称的,所以这个题目我们可以先找到中间节点,然后将中间反转,然后两个指针,一个从头开始,一个从反转后的头节点开始,一一比对,如果val不相等一定不是回文,如果相等,那么一定是回文链表。

偶数个数据时
在这里插入图片描述
奇数个数据时:
在这里插入图片描述
所以我们可以清楚的知道当rmid为空时就要结束循环。
代码如下:

// 计算中间节点
struct ListNode* midNode(struct ListNode* head)
{struct ListNode* fast = head,*slow = head;while(fast&&fast->next){slow = slow->next;fast = fast->next->next;}return slow;
}// 翻转链表
struct ListNode* reverseList(struct ListNode* head)
{struct ListNode* cur = head, *newhead = NULL,*next = NULL;while(cur){next = cur->next;cur->next = newhead;newhead = cur;cur = next;}return newhead;
}
bool isPalindrome(struct ListNode* head)
{//计算中间节点struct ListNode* mid = midNode(head);//反转链表struct ListNode* rmid =reverseList(mid);while(rmid){//不相等一定不回文,返回falseif(head->val!=rmid->val){return false;}head = head->next;rmid = rmid->next;} //循环结束一定是回文return true;
}

链表分割

在这里插入图片描述

这个题我们需要两个链表,然后遍历原链表,将小于x的尾插到head1,将大于等于x的尾插带head2,然后将两个链表链接一下,需要注意的是我们需要将head2的为尾节点的next置空,不然可能会出现带环链表,还有就是我们的head1有可能为空,这里我们使用带哨兵位的链表,就可以解决这个问题,但是head2也可能为空,这时我们就需要将head1的尾节点next置空,不然就会存在非法访问。

代码如下:

struct ListNode* partition(struct ListNode* head, int x)
{struct ListNode* head1,*tail1,*head2,*tail2;//开辟两个哨兵位head1 = tail1 = (struct ListNode*)malloc(sizeof(struct ListNode));head2 = tail2 = (struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* cur = head;while(cur){if(cur->val<x){//小于的尾插到tail1tail1->next = cur;cur = cur->next;tail1 = tail1->next;}else{//大于的尾插到tail2tail2->next = cur;cur = cur->next;tail2 = tail2->next;}}//链接两个链表tail1->next = head2->next;//防止出现带环链表tail2->next = NULL;if (head2->next == NULL){//第二个链表为空,这是要将这是要将tail1->next置空,不然会出现非法访问tail1->next = NULL;struct ListNode* next = head1->next;free(head2);free(head1);return next;}//保存头结点struct ListNode* next = head1->next;//释放哨兵位free(head1);free(head2);return next;
}

两个链表的交集

在这里插入图片描述

判断是否相交非常简单,我们只需要判断两个链表的为节点是否相同就可以了,如果相同,那么它们一定是相交的,我们就可以找相加的那个节点,我们在找尾的时候可以记录一下两个链表的长度,由于从相交的位置开始后面的节点都一样了,我们可以计算出长的那个链表比短的链表长多少,让长的链表先走多少步,然后让两个链表同时走,相等的第一个节点就是我们要求的。

代码如下:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{struct ListNode* curA = headA,*curB = headB;int s1 = 1;int s2 = 1;//找A链表的尾,顺表记录长度while(curA->next){curA= curA->next;s1++;}//找B链表的尾,顺表记录长度while(curB->next){curB= curB->next;s2++;}//尾节点不相等一定不相交if(curA!=curB){return NULL;}//计算差值int k = abs(s1-s2);//假设长的链表为Astruct ListNode* longNode = headA,*shortNode = headB;//如果B链表长,则将长链表赋值Bif(s1<s2){longNode = headB;shortNode = headA;}//长链表先走k步while(k--){longNode= longNode->next;}//寻找第一个相等的节点while(longNode!=shortNode){longNode = longNode->next;shortNode = shortNode->next;}return longNode;
}

链表循环

在这里插入图片描述

我们可以用快慢指针来解决这个问题,我们让慢指针走一步,快指针走两步,如果有环,那么当俩个指针都进入环中是,就是追击问题,如果快指针走到NULL,或者快指针的next为空,那么就意味着链表无环。

代码如下:

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

思考

1.如果slow走一步,fast走二步是不是一定可以追上?

答案是一定可以追上,为什么呢,假设slow进环时fast与它相距N步,那么每走一步,他们之间的距离减少一,而N一定小于一圈的长度,所以在一圈之内fast一定追上slow。

在这里插入图片描述
2.如果slow走一步,fast走三步是不是一定可以追上?

答案是不太一定,假设他们之间的距离还是N,如果N是偶数那么就追上了,如果N奇数,他们就会错过,假设圆的长度为C,他们的距离就会变成C-1,这是又要分情况了,假设C-1位奇数那么就一定追不上了,如果C-1位偶数那么在下一圈的追击中就会追上。

在这里插入图片描述

链表周期 II

在这里插入图片描述

方法一

我们需要推导一个公式,假设头到入环点的长度为L,然后假设他们在环中相遇的点为X,入环点到X的距离为N,然后整个环的长度为C,我们可以推导:

在这里插入图片描述

有了这个推导关系我们就可以写代码了。
代码如下:

struct ListNode *detectCycle(struct ListNode *head) 
{struct ListNode* slow = head,*fast = head;while(fast&&fast->next){fast = fast->next->next;slow = slow->next;//判断是否相遇if(fast==slow){struct ListNode* meet = fast,*cur = head;//一个从相遇点开始走,一个从头开始走while(meet!=cur){meet = meet->next;cur = cur->next;}//此时相遇的点就是入环点return meet;}}//出循环一定没有环return NULL;
}

方法二

我们还是找相遇点,然后我们把相遇点的next置空,保存相遇点的next,然后就变成了相交链表。

在这里插入图片描述

代码如下:

//找相交链表的第一个相交点struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{struct ListNode* curA = headA,*curB = headB;int s1 = 1;int s2 = 1;//找A链表的尾,顺表记录长度while(curA->next){curA= curA->next;s1++;}//找B链表的尾,顺表记录长度while(curB->next){curB= curB->next;s2++;}//尾节点不相等一定不相交if(curA!=curB){return NULL;}//计算差值int k = abs(s1-s2);//假设长的链表为Astruct ListNode* longNode = headA,*shortNode = headB;//如果B链表长,则将长链表赋值Bif(s1<s2){longNode = headB;shortNode = headA;}//长链表先走k步while(k--){longNode= longNode->next;}//寻找第一个相等的节点while(longNode!=shortNode){longNode = longNode->next;shortNode = shortNode->next;}return longNode;
}struct ListNode *detectCycle(struct ListNode *head) 
{struct ListNode* slow = head,*fast = head;while(fast&&fast->next){fast = fast->next->next;slow = slow->next;//判断是否相遇if(fast==slow){struct ListNode* meet = fast,*newhead = fast->next;//转换相交链表meet->next = NULL;//找第一个相交点,也就是入环点return getIntersectionNode(head,newhead);}}//出循环一定没有环return NULL;
}

总结一下:

方法一逻辑强,不好推导,但是推导出来代码好写
方法二逻辑没有那么强,适合我们普通人,但是代码量稍微大一点。

今天的分享就到这里结束了,感谢大家的关注和支持。

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

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

相关文章

策略模式(C++)

定义 定义一系列算法&#xff0c;把它们一个个封装起来&#xff0c;并且使它们可互相替换((变化)。该模式使得算法可独立手使用它的客户程序稳定)而变化(扩展&#xff0c;子类化)。 ——《设计模式》GoF 使用场景 在软件构建过程中&#xff0c;某些对象使用的算法可能多种多…

深入理解Streamlit中的按钮行为(四):示例与最佳实践

文章目录 1 前言&#x1f680;2 Streamlit中if st.button()的使用时机 &#x1f3af;&#x1f4a1;3 按钮的逻辑3.1 通过按钮显示临时消息的常用逻辑 &#x1f4e2;&#x1f4a1;3.2 状态保留按钮 &#x1fa84;&#x1f518;3.3 切换按钮 &#x1f504;&#x1f518;3.4 控制流…

Tensorrt 原生Activate 算子讲解

Tensorrt operators docs&#xff1a; Activation Apply an activation function on an input tensor A and produce an output tensor B with the same dimensions. import numpy as np from cuda import cudart import tensorrt as trt # 输入张量 NCHW nIn, cIn, hIn, wI…

Scrum敏捷开发流程图怎么画?

1. 什么是Scrum敏捷开发流程图&#xff1f; Scrum敏捷开发流程图是一种可视化工具&#xff0c;用于形象地描述Scrum敏捷开发方法中的工作流程和活动。Scrum敏捷开发流程图展示了项目从需求收集到产品交付的整个开发过程&#xff0c;帮助团队理解和跟踪项目进展&#xff0c;促…

02.Redis实现添加缓存功能

学习目标&#xff1a; 提示&#xff1a;学习如何利用Redis实现添加缓存功能 学习产出&#xff1a; 流程图 1. 准备pom环境 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId&g…

EXCEL,多条件查询数字/文本内容的4种方法

目录 1 问题&#xff1a;如何根据多条件查询到想要的内容 2 方法总结 2.1 方法1&#xff1a; sumif() 和sumifs() 适合查找符合条件的多个数值之和 2.2 方法2&#xff1a;使用lookup(1,0/((区域1条件1)*(区域2条件2)*....),结果查询区域) 2.3 方法3&#xff1a;使用 ind…

广西茶叶元宇宙 武隆以茶为媒 推动茶文旅产业融合发展

8月4日&#xff0c;重庆市武隆区启动为期3天的“武隆首届玩茶荟”。本次活动以“中国最美玩茶地——武隆”为主题&#xff0c;吸引众多国内知名专家、茶企和茶馆相关负责人&#xff0c;共同探索武隆茶文旅融合发展新路径和新业态。 广西茶叶元宇宙&#xff1a;广西茶叶元宇宙 …

React安装ant design组件库,并使用

ant design是一个很棒的组件库&#xff0c;官方地址&#xff1a;快速上手 - Ant Design 但是如何在React里面用起来&#xff0c;好像并不是很顺畅&#xff0c;没有像Vue里面那么友好&#xff0c;因为我踩过这个坑&#xff0c;虽然安装很简单&#xff0c;但是想要出样式&#x…

合并两个有序链表(leetcode)

题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]思路 每次递归都会比较当前两个节点的值&#xff0c;选择较小的节点作为合并后的链…

edge://settings/defaultbrowser default ie

Microsoft Edge 中的 Internet Explorer 模式 有些网站专为与 Internet Explorer 一起使用&#xff0c;它们具有 Microsoft Edge 等新式浏览器不支持的功能。 如果你需要查看其中的某个网站&#xff0c;可使用 Microsoft Edge 中的 Internet Explorer 模式。 大多数网站在新…

Java:如何破坏类加载器的双亲委派机制?

本文重点 我们前面分析过loadClass方法,我们可以发现,这个方法的逻辑就是双亲委派机制,也就是说只要不破坏这个方法,那么就不会破坏双亲委派机制。如果要想破坏双亲委派机制,我们需要在类中重写loadClass方法,只要这样,那么就不会走双亲委派机制了。 破坏还是不破坏双…

2023-08-05力扣今日五题-好题

链接&#xff1a; 剑指 Offer 52. 两个链表的第一个公共节点 题意&#xff1a; 如题 解&#xff1a; 非常有趣的双指针 首先我们不管他们是否有公共段啊&#xff0c;我们要知道一个指针从A出发走到A结尾&#xff0c;再从B出发走到B结尾&#xff0c;和从B出发最终到A结尾是…

麦肯锡战略思维四大原则

麦肯锡战略思维四大原则 曾任职麦肯锡、安永等国家国际知名咨询机构的周正元&#xff0c;在其著作《麦肯锡结构化战略思维》将其系统的整理呈现出来&#xff0c;便于学习和使用。 模型介绍 工作中的你&#xff0c;是不是经常遇到复杂问题&#xff0c;六神无主&#xff1f; 专业…

JAVA语言:如何自定义类加载器?

本文重点 前面的课程中&#xff0c;我们已经学习了双亲委派机制&#xff0c;如果想要自定义一个类加载器&#xff0c;那么我们只需要继承ClassLoader&#xff0c;并且定义好自己的findClass就可以了&#xff0c;也就是自己的类加载器是如何进行工作的&#xff0c;而loadClass就…

Java thymeleaf bug排查记录

刚学Java 做项目时报了一个错误 一时间看的莫名其妙 EL1008E: Property or field createTime cannot be found on object of type java.util.HashMap - maybe not public or not valid? 随即向上排查至第一个报错&#xff0c;发现是thymeleaf渲染时报错。 Exception proces…

【Python从入门到进阶】31、使用JSONPath解析淘票票网站地区接口数据

接上篇《30、JSONPath的介绍和使用》 上一篇我们介绍了JSONPath的基础和具体使用&#xff0c;本篇我们来具体使用JSONPath&#xff0c;来解析淘票票网站的地区接口数据。 一、引言 1、JsonPath的作用和用途&#xff1f; JsonPath是一种用于在JSON数据中进行查询和提取的表达…

【Jmeter】压测mysql数据库中间件mycat

目录 背景 环境准备 1、下载Jmeter 2、下载mysql数据库的驱动包 3、要进行测试的数据库 Jmeter配置 1、启动Jmeter图形界面 2、加载mysql驱动包 3、新建一个线程组&#xff0c;然后如下图所示添加 JDBC Connection Configuration 4、配置JDBC Connection Configurati…

【GEMM预备工作】行主序和列主序矩阵的内存中的连续性,解决理解问题

在内存存储中&#xff0c;默认矩阵是按照行优先储存的&#xff0c;即矩阵的每一列在内存中是连续的。行优先矩阵储存中行数据是不连续的。 而对于列主序的矩阵&#xff0c;是按照列优先储存的&#xff0c;即矩阵的每一行在内存中是连续的。列优先矩阵储存中列数据是不连续的&am…

OPENCV C++(一) 二进制和灰度原理 处理每个像素点值的方法

#include <opencv2/opencv.hpp> using namespace std; using namespace cv;必须包含的头文件&#xff01; 才能开始编写代码 读取相片 一般来说加个保护程序 不至于出error和卡死 Mat image imread("test.webp"); //存放自己图像的路径 if (image.empty()){p…

SOLIDWORKS软件如何批量加图号

当我们在做模型设计时&#xff0c;不管是新研发还是改型设计&#xff0c;都需要规范模型的属性信息&#xff0c;其中必不可少的就是图号或代号。但是一套产品是由很多个零件组成的&#xff0c;每个零件的属性都需要去规范&#xff0c;一个一个改其实工作量也不小&#xff0c;今…