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

链表OJ习题(2)

一. 牛客网 链表的回文结构

https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa

思路

1、偶数情况:

2、奇数情况:

代码实现

class PalindromeList {public://1.找中间节点ListNode* middleNode(ListNode* head) {//快慢指针ListNode* fast, * slow;fast = head;slow = head;while (fast != NULL && fast->next != NULL) {slow = slow->next;fast = fast->next->next;}return slow;}//2.翻转以中间节点为头的链表ListNode* reverseList(ListNode* head) {if (head == NULL) {return head;}ListNode* n1, *n2, *n3;n1 = NULL;n2 = head;n3 = n2->next;while (n2) {n2->next = n1;n1 = n2;n2 = n3;if (n3)n3 = n3->next;}return n1;}bool chkPalindrome(ListNode* A) {//1.找中间节点ListNode* mid = middleNode(A);//2.翻转以中间节点为头的链表ListNode* right = reverseList(mid);//3.遍历原链表和反转后的链表,比较节点的值是否相等ListNode* left = A;while (right) {if (left->val != right->val) {return false;}left = left->next;right = right->next;}return true;}
};

二. leetcode 160 相交链表

https://leetcode.cn/problems/intersection-of-two-linked-lists/description/

思路

共存在三种相交情况(一定会在末尾相遇):

1、在末尾处相交

2、在起点处相交

           

3、在中间处相交

不存在以下这种情况:因为 c1 只有1个next指针,只能指向一个节点

代码实现

typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {ListNode* pa=headA;ListNode* pb=headB;int sizeA=0,sizeB=0;while(pa){sizeA++;pa=pa->next;}while(pb){sizeB++;pb=pb->next;}//求长度差int gap=abs(sizeA-sizeB);//求绝对值//假设法ListNode* longList=headA;ListNode* shortList=headB;if(sizeA<sizeB){longList=headB;shortList=headA;}while(gap--){longList=longList->next;}while(shortList){if(longList==shortList){return shortList;}shortList=shortList->next;longList=longList->next;}return NULL;
}

三. 环形链表 |

思路

https://leetcode.cn/problems/linked-list-cycle/description/

slow⼀次走⼀步,fast⼀次走2步,fast先进环,假设slow也走完⼊环前的距离,准备进环,此时fast 和slow之间的距离为N,接下来的追逐过程中,每追击⼀次,他们之间的距离缩小1步

追击过程中fast和slow之间的距离变化:

因此,在带环链表中慢指针走⼀步,快指针走两步最终⼀定会相遇。

思考2:快指针⼀次走3步,走4步,...n步⾏吗?

答案是可以的,有兴趣的同学可以自行推导一下,这里就不再赘述了

代码实现

typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {if(head==NULL){return false;}//快慢指针ListNode*slow,*fast;slow=fast=head;while(fast!=NULL && fast->next!=NULL){slow=slow->next;fast=fast->next->next;//如果快指针与慢指针相遇,那么一定有环if(slow==fast){return true;}}return false;
}

四. 环形链表 ||

https://leetcode.cn/problems/linked-list-cycle-ii/description/

思路

说明:
H为链表的起始点,E为环入口点,M与判环时候相遇点
设:
环的⻓度为R,H到E的距离为L,E到M的距离为 X ,则:M到E的距离为 R-X

在判环时,快慢指针相遇时所⾛的路径⻓度:
fast: L+X + nR 
slow:L+X 

注意:
1.当慢指针进⼊环时,快指针可能已经在环中绕了n圈了,n⾄少为1
因为:快指针先进环⾛到M的位置,,最后⼜在M的位置与慢指针相遇
2.慢指针进环之后,快指针肯定会在慢指针⾛⼀圈之内追上慢指针
因为:慢指针进环后,快慢指针之间的距离最多就是环的⻓度,⽽两个指针在移动时,每次它们⾄今
的距离都缩减⼀步,因此在慢指针移动⼀圈之前快,指针肯定是可以追上慢指针的,⽽快指针速度是慢指针的两倍,因此有如下关系是:
2 * (L+X)=L+X+nR
L+X=nR
L=nR-X
L = (n-1)R+(R-X)
(n为1,2,3,4......,n的大小取决于环的大小,环越小n越⼤)

因为R为环的周长,所以无论前面的系数是多少,最终都是环周长的整数倍
所以:
L=R-X 
即:⼀个指针从链表起始位置运行,⼀个指针从相遇点位置绕环,每次都走⼀步,两个指针最终会在入口点的位置相遇

代码实现

typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) {ListNode* slow=head;ListNode* fast=head;while(fast && fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){//带环//头节点到入环节点的距离 == 相遇节点到入环节点的距离ListNode* pcur=head;//这里就再一次用到了head,所以之前不能用head遍历while(pcur!=slow){pcur=pcur->next;slow=slow->next;}return pcur;}}return NULL;
}

五. 随机链表的复制

https://leetcode.cn/problems/copy-list-with-random-pointer/description/

思路

1、在原链表基础上拷贝节点并插入到原链表中

2、设置 radom 指针(注:这里未将所有的radom指针画完)

3、断开与原链表的链接(注:这里未将所有的radom指针画完)

代码实现

/*** Definition for a Node.* struct Node {*     int val;*     struct Node *next;*     struct Node *random;* };*/
typedef struct Node Node;
Node* BuyNode(int x) {Node* newnode = (Node*)malloc(sizeof(Node));if (newnode == NULL) {return NULL; // 处理内存分配失败的情况}newnode->val = x;newnode->next = newnode->random = NULL;return newnode;
}//在原链表基础上拷贝节点并插入到原链表中
void AddNode(Node* head) 
{Node* pcur=head;while(pcur){Node* newnode=BuyNode(pcur->val);Node* next=pcur->next;newnode->next=next;pcur->next=newnode;pcur=next;}
}//设置radom
void setRandom(Node* head)
{Node* pcur=head;while(pcur){Node* copy=pcur->next;if(pcur->random)copy->random=pcur->random->next;pcur=copy->next;}
}struct Node* copyRandomList(struct Node* head) {if(head==NULL){return head;}//在原链表基础上拷贝节点并插入到原链表中AddNode(head);//设置radomsetRandom(head);//断开链表Node* pcur=head;Node* copyHead,* copyTail;copyHead=copyTail=pcur->next;while(copyTail->next){pcur=copyTail->next;copyTail->next=pcur->next;copyTail=copyTail->next;}return copyHead;
}

总结

本篇博客深入解析了经典的链表OJ习题,旨在帮助读者掌握链表操作的核心技巧与解题思路,通过对典型例题的剖析和画图理解,助你巩固数据结构基础。

如果大家在练习中发现新的解题角度,或是有没搞懂的知识点,欢迎在评论区留言讨论。后续我也会持续更新数据结构相关的 OJ 解析,咱们一起在刷题中夯实基础,稳步进阶!

http://www.dtcms.com/a/350652.html

相关文章:

  • 搭建基于LangChain实现复杂RAG聊天机器人
  • AI在软件研发流程中的提效案例
  • 在vue3后台项目中使用热力图,并给热力图增加点击选中事件
  • Java中删除字符串首字符
  • 【51单片机】【protues仿真】基于51单片机数码管温度报警器系统
  • AR眼镜赋能水利智能巡检的创新实践
  • 算法题打卡力扣第167题:两数之和——输入有序数组(mid)
  • VASP计算层错能(SFE)全攻略2
  • python自学笔记12 NumPy 常见运算
  • QT(1)
  • 独立显卡接口操作指南
  • 小程序开发指南(四)(UI 框架整合)
  • Linux系统网络管理
  • UE5 UI遮罩
  • 人形机器人产业风口下,低延迟音视频传输如何成为核心竞争力
  • Linux笔记9——shell编程基础-3
  • OpenFeign的原理解析
  • FMS回顾和总结
  • C++ 中 `std::map` 的 `insert` 函数
  • 【机器学习项目 心脏病预测】
  • 【广告系列】流量归因模型
  • centos 用 docker 方式安装 dufs
  • 【C++11】auto关键字:自动类型推导
  • Python爬虫实战: 爬虫常用到的技术及方案详解
  • Leetcode top100之链表排序
  • Swift 解法详解 LeetCode 362:敲击计数器,让数据统计更高效
  • 【猿人学】web第一届 第16题 js-逆向 windows蜜罐 / webpack初体验
  • 通过C#上位机串口写入和读取浮点数到stm32实战5(通过串口读取bmp280气压计的数值并在上位机显示)
  • java 并发编程八股-多线程篇
  • 【已解决】统信UOS安装后没有有线网络,缺少Chengdu Haiguang IC Design Co., Ltd. 10 Gb Ethernet网卡驱动