目录
一.普通快慢
一.返回倒数第K个结点
面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode)
思路很简单就是先让fast指针先走k步,那么slow也就是慢指针只会走N-K步(N为总长度),
我们返回的也是slow走(N-K)步的位置
代码如下
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
int kthToLast(struct ListNode* head, int k)
{
//先让fast指针走K步
struct ListNode* fast=head;
struct ListNode* slow=head;
while(k--)
{
fast=fast->next;
}
while(fast)
{
fast=fast->next;
slow=slow->next;
}
return slow->val;
}
二.相交链表
解答过程和思路很简单就是先让长的走到与短的相等最后一起走如果相等则返回相交链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
//进行遍历找到最长链表
int lenthA=0;
int lenthB=0;
ListNode* curA=headA;
ListNode* curB=headB;
while(curA)
{
++lenthA;
curA=curA->next;
}
while(curB)
{
++lenthB;
curB=curB->next;
}
//找到长链表重新赋值
if(lenthB>lenthA)
{
curA=headB;
curB=headA;
}
else
{
curA=headA;
curB=headB;
}
int temp=abs(lenthA-lenthB);
while(temp--)//先让长的链表走到相等位置
{
curA=curA->next;
}
while(curA&&curB)
{
if(curA==curB)
return curA;
curA=curA->next;
curB=curB->next;
}
return NULL;
}
三.回文链表![](https://img-blog.csdnimg.cn/direct/d80c5a7c6b8c454f8b315c0e52006c5c.png)
链表的回文结构_牛客题霸_牛客网 (nowcoder.com)z
这里我们将会运用到两个链表的知识,一个是链表的反转,一个是运用快慢指针来寻找中间值
首先我们要思考怎么比较回文结构,我觉得可以这样来将前面的与后面的一一进行比较,直到中间结束,如果有一个不相等返回false不是回文
但是前面与后面相比比较复杂所有我们先将其(从中间开始)进行反转
//有啦下以上的思考我们来做这道题
如果我们想要将链表进行反转肯定要先找到中间的位置,运用快慢指针找到中间位置
找到后进行反转,代码如下
ListNode* FindMid(ListNode* head)//运用快慢指针找到中间位置
{
ListNode* fast=head;
ListNode* slow=head;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
}
return slow;
}
ListNode* ReverseList(ListNode* head)//找到位置后进行反转
{
ListNode* pre=NULL;
ListNode* cur=head;
ListNode* next=head->next;
while(cur)
{
cur->next=pre;
pre=cur;
cur=next;
if(next)
next=next->next;
}
return pre;
}
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
if(A==NULL)
return false;
ListNode* mid=FindMid(A);//保存中间位置
ListNode* reallyMid=ReverseList(mid);//反转后返回新的中间值
ListNode* head=A;
while(head&&reallyMid)
{
if(head->val!=reallyMid->val)//进行比较
{
return false;
}
head=head->next;
reallyMid=reallyMid->next;
}
return true;
}
};
二.循环单链表中快慢的使用
一.判断是否为环形链表
//一道经典的快慢指针题目板子题详情介绍可看我的这篇 下面那道题也是
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head)
{
if(head==NULL||head->next==NULL)
return false;
struct ListNode *fast=head->next->next;
struct ListNode *slow=head->next;
while(fast&&fast->next)
{
if(fast==slow)
{
return true;
}
fast=fast->next->next;
slow=slow->next;
}
return false;
}
二.返回环的初始结点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head)
{
if(head==NULL||head->next==NULL)
{
return NULL;
}
struct ListNode *fast=head;
struct ListNode *slow=head;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
{
fast=head;
while(1)
{
if(fast==slow)
{
return fast;
}
fast=fast->next;
slow=slow->next;
}
}
}
return NULL;
}
三.复制单链表(综合题目)
因为新生成的链表要指向新生成的链表所以有这样的一个巧妙做法
//这道题其实就三个思路
思路
一.在当前链表后面进行copy
这里运用了一个相当巧妙的做法,在原链表的后面进行一次copy原链表,将next指针与val值进行赋值,random先不管
二.对random进行复制
c然后可以对新链表的random赋值,(copy->random=current->random->next)因为random就在久链表的random->next
三.将原链表剪下来
将原链表剪下来即可
typedef struct Node Node;
struct Node* copyRandomList(struct Node* head)
{
//在当前的链表后面进行copy链表
if(head==NULL)
return NULL;
Node *cur=head;
while(cur)
{
Node* newnode=(Node*)malloc(sizeof(Node));
Node* next=cur->next;
newnode->val=cur->val;
newnode->next=cur->next;
cur->next=newnode;
cur=next;
}
//进行random的赋值
cur =head;
while(cur)
{
if(cur->random==NULL)
{
cur->next->random=NULL;
}
else
{
cur->next->random=cur->random->next;
}
cur=cur->next->next;
}
//将原链表剪下来
cur =head;
Node* newHead=(Node*)malloc(sizeof(Node));
Node* tail=newHead;
while(cur)
{
tail->next=cur->next;
cur=cur->next->next;
tail=tail->next;
}
return newHead->next;
}
由于个人精力有限,如有不对欢迎指出让我们一起进步吧!!
小bit!!!