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

【链表】算法题(二) ----- 力扣/牛客

一、链表的回文结构

思路:

找到链表的中间节点,然后逆置链表的后半部分,再一一遍历链表的前半部分和后半部分,判断是是否为回文结构。

快慢指针找到链表的中间节点

slow指针指向的就是中间节点

逆置链表后半部分

逆置链表后半部分

遍历链表前半部分和后半部分

如果left和right指向的数据不相等,就跳出循环,返回false;如果遍历到left或者right为NULL,数据都相等,那么链表具有回文结构,返回true。

这里如果是奇数个节点:

遍历结束后:

class PalindromeList { public: //找链表中间节点 ListNode* Listmid(ListNode* phead) { ListNode* fast, *slow; fast=slow=phead; while(fast && fast->next) { slow=slow->next; fast=fast->next; } return slow; } //逆置 ListNode* reverse(ListNode* phead) { ListNode* l1,*l2,*l3; l1=NULL; l2=phead; while(l2) { l3=l2->next; l2->next=l1; l1=l2; l2=l3; } return l1; } bool chkPalindrome(ListNode* A) { // write code here //找到链表中间节点 ListNode* mid=Listmid(A); //逆置后半部分 ListNode* phead = reverse(mid); //比较 ListNode* left, *right; left=A; right=phead; while(right && left) { if(right->val!=left->val) { return false; } left=left->next; right=right->next; } return true; } };

二、相交链表

判断两个链表是否相交,如果相交就返回相交节点,如果链表不相交,那就返回NULL;

思路:

先遍历两个链表,记录两个链表的节点个数;再同时遍历两个链表 ,让节点个数多的链表先往前走s(链表的节点个数差);同时遍历两个链表,如果指向链表的指针相等,就返回当前节点;如果遍历链表结束后,都没有相等的节点,那就返回NULL。

typedef struct ListNode ListNode; struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) { if (headA == NULL) { return NULL; } if (headB == NULL) { return NULL; } int sizeA = 0, sizeB = 0; ListNode *l1, *l2; l1 = headA; l2 = headB; while (l1) { sizeA++; l1 = l1->next; } while (l2) { sizeB++; l2 = l2->next; } ListNode* shortList = headA; ListNode* longList = headB; int s = abs(sizeA - sizeB); if (sizeA > sizeB) { shortList = headB; longList = headA; } while (s) { s--; longList = longList->next; } while (longList && shortList) { if (longList == shortList) { return longList; } longList = longList->next; shortList = shortList->next; } return NULL; }

三、环形链表1

判断 链表中是否存在环,如果存在就返回true,如果不存在就返回false;

思路:快慢指针

定义两个指针fast和slow;遍历链表,fast每次向前走两步,slow每次向前走一步,如果链表存在环,fast与slow指针一定会相遇;如果遍历链表,fast或者fast->next为NULL,则链表不存在环。

根据题目所给示例来分析一下:

首先定义两个指针fast slow

fast向前走两步,slow向前走一步

fast向前走两步,slow向前走一步

fast向前走两步,slow向前走一步

此时,fast和slow相遇,证明链表中存在环,返回true。

如果链表不存在环结构,遍历过程中fast或者fast->next指针会等于NULL,将这个作为结束条件即可。

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

四、环形链表2

上面只是让我们判断链表是否带环,这道题让我们返回链表环的起始节点,如果不存在环就返回NULL。

思路:

使用快慢指针找到快慢指针的相遇节点;再定义两个指针从相遇节点和链表头结点开始遍历,两个指针相遇时的节点就是链表环的起始节点。

根据题目的示例来分析:

先找到链表快慢指针的相遇节点:

定义两个指针从链表头部和相遇节点开始遍历链表

遍历链表直到两个指针相遇

两个指针相遇,此时指针指向的节点就是链表环的起始节点。

typedef struct ListNode ListNode; ListNode* hasCycle(struct ListNode *head) { ListNode* fast, *slow; fast=slow=head; while(fast && fast->next) { fast=fast->next->next; slow=slow->next; if(slow == fast) { return slow; } } return NULL; } struct ListNode *detectCycle(struct ListNode *head) { //找到快慢指针相遇节点 ListNode* pos=hasCycle(head); if(pos==NULL) { return NULL; } //从头结点和相遇节点开始遍历 ListNode* ptail=head; while(1) { if(pos==ptail) { return pos; } pos=pos->next; ptail=ptail->next; } }

五、随机链表的复制

这里题目上提到了一个深拷贝

思路:

先在原链表的基础上创建节点,形成新的链表,再给链表节点的random指针赋值,最后断开新链表和原链表的连接即可。

深拷贝原链表

拷贝过后

给random指针赋值

断开新链表和原链表之前的连接

这样就深拷贝了原链表,返回新链表的头节点即可。

typedef struct Node Node; // 创建节点 Node* BuyNode(int x) { Node* newnode = (Node*)malloc(sizeof(Node)); newnode->next = newnode->random = NULL; newnode->val = x; return newnode; } // 深拷贝 void CopyList(Node** head) { Node* ptail = *head; Node* next = NULL; while (ptail) { next = ptail->next; Node* newnode = BuyNode(ptail->val); newnode->next = next; ptail->next = newnode; ptail = next; } } void Connect(Node** head) { Node* ptail = *head; Node* copy = (*head)->next; while (ptail) { copy = ptail->next; if (ptail->random) copy->random = ptail->random->next; ptail = copy->next; } } struct Node* copyRandomList(struct Node* head) { if (head == NULL) { return NULL; } // 深拷贝原链表 CopyList(&head); // 连接random指针 Connect(&head); // 断开链表 Node* ptail = head; Node* newhead = head->next; Node* copy = head->next; while (ptail->next->next) { ptail=copy->next; copy->next = copy->next->next; copy = copy->next; } return newhead; }
http://www.jsqmd.com/news/598808/

相关文章:

  • 图书借阅管理系统
  • RStudio Server卡在‘R启动慢’?别慌,手把手教你清理session文件恢复访问
  • 印度裔全球崛起:一场无硝烟的人才与人口博弈
  • Retinaface+CurricularFace人脸识别:高清人脸比对效果案例分享
  • 开天辟地 初出茅庐
  • 【2026 AI 实战】用 Python 做一个本地 AI 聊天机器人,零基础也能跑通
  • 笔记04
  • 从社交推荐到药物发现:GAT(图注意力网络)在5个工业级场景下的落地实践
  • 双剪切式固体废物破碎机结构设计
  • 快速原型利器:在快马平台一键对比不同AI模型的代码生成效果
  • Z-Image-Turbo-辉夜巫女应用:快速生成动漫角色,打造个人风格画师
  • AMD锐龙处理器终极调优指南:RyzenAdj完整配置与实战教程
  • 【花雕学编程】嵌入式 AI Agent:从云端到终端,开启物理世界智能新范式
  • 基于FOC的无刷平衡车设计(开题报告)
  • Docker 常用命令速查手册
  • 工业质检实战:如何用Real-IAD数据集快速搭建异常检测模型(附完整代码)
  • 如何用Winhance实现Windows系统深度优化:全面配置指南
  • 洛谷P2731 [USACO3.3] 骑马修栅栏 Riding the Fences
  • SteamAchievementManager终极指南:如何安全掌控你的Steam游戏成就
  • YOLO12边缘设备部署指南:Nano版仅需2GB显存,低配置也能跑
  • BBDown进阶指南:从入门到精通的B站视频下载解决方案
  • H-ui.admin:如何在30分钟内构建企业级后台管理系统?
  • 信创运维避坑指南:统信UOS服务器离线安装软件,这些细节你注意了吗?
  • OpenClaw从入门到应用——频道:IRC
  • 圣女司幼幽-造相Z-Turbo进阶用法:用Python脚本批量生成角色图教程
  • 别再乱猜了!手把手教你用数字万用表的‘通断档’精准定位电路板上的信号短路
  • jupyter Kernel Disconnected崩溃的修复
  • 【花雕动手做】ESP32-S3 + MimiClaw 实战:通过飞书自然语言指令控制板载 WS2812 彩灯
  • P社游戏Mod管理神器:手把手教你用C++打造自动排序工具
  • 如何掌握Cucumber.js API接口:从CLI到编程式调用的完整指南