文章目录
前言
本次题目包括环形链表(力扣简单)
环形链表2(力扣中等)
复制带随机指针的链表(力扣中等)
环形链表
连接
题目描述
及判断一个单链表内是否带环即可如果带环就返回true不带环就返回false.
我们使用快慢指针来解决这个问题
思路
快慢指针
定义fast和slow,fast一次跳两个节点,slow一次跳一个节点
让fast去追赶slow就好
如果fast先进入环内循环等到slow进入环内后fast如果是带环的就一定可以追上slow如果不带环就通过if判断条件结束进程就好👍
正确代码
bool hasCycle(struct ListNode *head)
{
if(head==NULL)
{
return false;
}//head为空直接false
struct ListNode *fast = head->next;
struct ListNode *slow = head;
while(fast != slow)
{
if(fast==NULL||fast->next==NULL||slow == NULL)
{
return false;
}//检测fast和slow
fast = fast->next->next;
slow = slow->next;
}
//循环结束后返回true.
return true;
}
环形链表2
力扣中等(这道题主要是找规律和公式)连接
题目描述
对上一题进行了升级,我们要找到环形链表的节点.
正确代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head)
{
if(head == NULL)
{
return NULL;
}
struct ListNode *slow = head;
struct ListNode *fast = head;
while(fast&&fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast==slow)
{
struct ListNode *meet = slow;
struct ListNode *start = head;
while(start!=meet)
{
start = start->next;
meet = meet->next;
}
return meet;
}
}
return NULL;
}
思路讲解
步骤
- 首先判空
- 通过快慢指针来判断是否为带环链表
- 追赶上就进入if条件句内
- if条件内通过fast的速度是slow的二倍推出的距离相同得出代码即可得出meet(主要讲解)
前三步不需要讲,都在代码里了.
第四步讲一下如何推断的距离相同以及那两段的距离相同👍
开始:
首先我们需要表达出fast和slow各自走的路程大小(画图理解较好)—分两种情况
我直接将两种情况融合成为一种情况好了🤪
情况一包括了情况二,情况二只是情况只是情况一的特殊情况而已👍.
(没想到我也能跟别人讲数学知识=-=明明只是数学渣渣)
好
我们就讲情况一好了😜.
通过图来讲 好一些.
(注:下图是fast已经追赶上slow的情况)
(舒文的闲话: 至于为啥要以fast和slow相遇时的情况作图讲解其实也很简单,因为我们就只能得到fast和slow相遇时的情况😜.)
我们先来找他们的关系式吧.
- slow作为慢指针它一定是不会转两圈及以上的因为fast会追上它
- 而🔆fast如果在slow没进环之前是有可能已经转了n圈🔆了
- 我们再通过fast走的路程是slow的二倍即可得到一下表达式
2L+2X = L+X+nC
移动一下可以得到以下式子
L = nC-X.
我们让一个变量从头走,让另一个变量从fast和slow相遇的地方走,当他俩相同时我们就得到了交点👍.
这也是我代码所实现的
struct ListNode *meet = slow;
struct ListNode *start = head;
while(start!=meet)
{
start = start->next;
meet = meet->next;
}
return meet;
代码思想不难主要是公式的推导.希望大家可以看懂😜.
复制带随机指针的链表😫
实话实说,这倒是我进入数据结构之后遇见的最难的题了😫.
巧方法
巧方法的思路其实也是比较简单的.
先创建链表并附在原链表的后面.
如图:
这也是下面代码所实现的👍
struct Node* cur = head;
while(cur!=NULL)
{
struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
copy->val = cur->val;
copy->next = cur->next;
cur->next = copy;
cur = cur->next->next;
}
然后对cur进行赋值成head让他继续搞随机指针🤪.
先看看代码吧
cur = head;
while(cur != NULL)
{
if(cur->random == NULL)
{
cur->next->random = NULL;
cur = cur->next->next;
}
else
{
cur->next->random = cur->random->next;
cur = cur->next->next;
}
}
最后一步,将链表拆下来.
这一步最难搞了😫
将copy的链表拆下时要注意一下细节
cur = head;
struct Node* copyhead = head->next;
struct Node* copytail = copyhead;
if(copyhead->next==NULL)
{
return copyhead;
}
while(cur!=NULL)
{
struct Node* copy = cur->next;
struct Node* curnext = copy->next;
copytail->next = copy;
copytail = copy;
cur->next = curnext;
cur = curnext;
}
好这样整体思路就确定下来了🤪.
但是这样的循环解决不了单单一个空间的情况不过这种情况我们一个if就可以解决了.
正确代码
/**
* Definition for a Node.
* struct Node {
* int val;
* struct Node *next;
* struct Node *random;
* };
*/
struct Node* copyRandomList(struct Node* head)
{
if(head==NULL)
{
return NULL;
}
struct Node* cur = head;
while(cur!=NULL)
{
struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
copy->val = cur->val;
copy->next = cur->next;
cur->next = copy;
cur = cur->next->next;
}
cur = head;
while(cur != NULL)
{
if(cur->random == NULL)
{
cur->next->random = NULL;
cur = cur->next->next;
}
else
{
cur->next->random = cur->random->next;
cur = cur->next->next;
}
}
cur = head;
struct Node* copyhead = head->next;
struct Node* copytail = copyhead;
if(copyhead->next==NULL)
{
return copyhead;
}
while(cur!=NULL)
{
struct Node* copy = cur->next;
struct Node* curnext = copy->next;
copytail->next = copy;
copytail = copy;
cur->next = curnext;
cur = curnext;
}
return copyhead;
}
结尾
机器人🤤,嘿嘿,.🤤.舒文最爱机器人了🤤.