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

【链表OJ】常见面试题 3

文章目录

  • 1.[环形链表II](https://leetcode.cn/problems/linked-list-cycle-ii/description/)
  • 1.1 题目要求
    • 1.2 快慢指针
    • 1.3 哈希法
  • 2.[随机链表的复制](https://leetcode.cn/problems/copy-list-with-random-pointer/description/)
    • 2.1 题目要求
    • 2.2 迭代法

1.环形链表II

环形链表II

1.1 题目要求

找到环形链表的入口并返回该节点,如果找不到就返回NULL。

1.2 快慢指针

在话 环形链表I中我们就用到了,快慢指针来判断一个链表中是否存在环。在环形链表I中已经解释了为什么会相遇。可是现在的问题是找到环的入口,我们的快慢指针好像做不到吧。
别急嘛,下面我将用数学的方式来证明可以做到!
数学证明
初始时,快慢指针都在链表的起始位置,在指针开始运动前我们要了解,快指针的速度的慢指针的两倍,也就说明了快指针的运动的路程是慢指针的两倍
定义快指针为红色箭头,慢指针为蓝色箭头。
起始

运动开始,当运动到慢指针刚好进入到环中时,快指针已经在环中运动了k圈了(k>=0
慢指针开始入环

此时的慢指针在A点,快指针在B点。AB距离为x,BA距离为y慢指针运动路程为z,快指针运动距离为k*(x+y)+x
根据快指针的运动路程是慢指针的两倍可得

2*z = k*(x+y)+x;
化简为
z = k*(x+y)+x

将图中的z替换得:
过渡

下面就是快慢指针相遇时刻,根据图中得距离BA为y,因为快指针的速度是慢指针的两倍,那么就说明了它们的相遇时刻是慢指针再运动y距离的时刻,此时的快指针运动了2y
快指针与慢指针相遇

现在它们相遇了,从图中观察,AC的距离为x。然后环的大小为x+y,以及从head到A的距离为x+k(x+y),这不就说明了,我们只要派出一个慢指针从head运动到A不就可以了吗,让环慢指针在环中转k圈,环外的慢指针也运动了k(x+y)的距离,此时它们离A都只差x,同时速度又是一样,由此两个慢指针是会在A点相遇的。

证明过程中的图片来源:Shawxing精讲算法

struct ListNode *detectCycle(struct ListNode *head) {struct ListNode* fast = head;struct ListNode* slow =head;while(fast&&fast->next){fast = fast->next->next;slow = slow->next;if(slow == fast){struct ListNode* cur = head;while(cur!=slow){cur = cur->next;slow = slow->next;}if(cur==slow)return cur;}}return NULL;
}

1.3 哈希法

利用哈希表unordered_map来存储链表的每个节点,链表存在环时,一定会有重复的节点进入哈希表,我们只要关注第一个重复加入哈希表的节点即可。

用c写很麻烦,代码我用c++写的。

class Solution {
public:ListNode *detectCycle(ListNode *head) {unordered_map<ListNode*,bool> cnt;ListNode* cur = head;while(cur){if(cnt.find(cur)!=cnt.end()){return cur;}cnt[cur] = true;cur = cur->next;}return nullptr;}
};

2.随机链表的复制

随机链表的复制

2.1 题目要求

创建一个新链表,这个新链表所有的节点、next链接和random链接都要与原链表完全相同,返回新链表的头。

2.2 迭代法

先创建和原链表值相同的节点,让原链表中的节点指向新创建的节点前,用新创建的节点指向原节点的下一个节点。
copy节点的创建

处理random
在把cur指向head,重新遍历链表,因为原本的链表因为新节点的加入有所改变,当时我们还是要让cur每次都指向原链表的节点,再创建一个copy指向新加入的链表。
因为一一配对的原因,我们只需要让copy节点指向原先节点指向的random的下一个节点就可以了就可以,不过有个例外就指向NULL的节点,特别判断一下就可以了
copy的random的指向

链接copy节点
把copy指向原链表节点的指针统统指向copy节点就可以了
copy节点最后的链接

struct Node* copyRandomList(struct Node* head) {struct Node* cur = head;while(cur){struct Node* copy = (struct Node*)malloc(sizeof(struct Node));copy->val = cur->val;copy->next = cur->next;cur->next = copy;copy->random = NULL;cur = copy->next;}cur = head;while(cur){struct Node* copy = cur->next;struct Node* next = copy->next;if(cur->random == NULL)copy->random = NULL;elsecopy->random = cur->random->next;cur = next;}//链接copy节点struct Node* phead = NULL;struct Node* tail = NULL;cur = head;while(cur){struct Node* copy = cur->next;struct Node* next = copy->next;if(phead == NULL){phead = copy;tail = phead;}else{tail->next = copy;tail = copy;}cur = next;}return phead;
}

那么关于链表题目的讲解就先到此为止了,如果大家对链表的题目还是很感兴趣下去以后可以刷这里的题:力扣链表和牛客链表的题目

http://www.lryc.cn/news/416694.html

相关文章:

  • Linux学习笔记9(Linux包管理)
  • 论文阅读《Geometric deep learning of RNA structure》
  • 宏集方案 | 传统建筑智能化改造,迈向物联新时代
  • 如果服务器更改Web端口会减少被攻击的风险吗?
  • vim列编辑模式
  • 如何实现pxe安装部署
  • 机器学习常见模型
  • 【python案例】基于Python 爬虫的房地产数据可视化分析设计与实现
  • 如何在Python中诊断和解决内存溢出问题
  • 什么是爬虫软件?这两个爬虫神器你必须要试试
  • 记录|MVS和VM软件使用记录
  • 算法通关:014_1:用栈实现队列
  • 【C#】Random
  • MongoDB简介及其在Java中的应用
  • JSON-LD上下文将属性映射到RDF IRIs示例
  • Spring的监听机制详解
  • Cache结构
  • 国产版Sora复现——智谱AI开源CogVideoX-2b 本地部署复现实践教程
  • 怎么读取FRM、MYD、MYI数据文件
  • Leetcode3226. 使两个整数相等的位更改次数
  • Linux笔记-3()
  • Apache漏洞复现CVE-2021-41773
  • GIT如何将远程指定分支的指定提交拉回到本地分支
  • 鸿蒙图形开发【3D引擎接口示例】
  • C#实现数据采集系统-系统优化服务封装
  • 数据结构与算法--栈、队列篇
  • 【程序、游戏、人生】致敬飞逝的3年和新的开始
  • 第三届人工智能、人机交互与机器人国际会议
  • AWS生成式AI项目的全生命周期管理
  • windows go grpc