1 相交链表
判断链表是否相交:两个链表的尾节点相同,两个链表一定相交
思路:(1)求两个链表的长度,求得两个链表的长度差为x
(2)让表较长的表头先走x步
(3)让两个指针一起走,看走到链表尾部前是否有两个链表指向相同的情况(找相同的节点)
链表相交有三种情况:
代码如下:
typedef struct LIstNode ListNode
struct LIstNode* getTntersectionNode(struct ListNode)
{
//求链表长度
ListNode* pa = headA;
ListNode* pb = headB;
int sizaA = 0,sizeB = 0;
while(pa)
{
++sizeA;
pa = pa->next;
}
while(pb)
{
++sizeB;
pb = pb->next;
}
//求长度差
int gap = abs(sizeA - sizeB);
//定义长短链表
ListNode* shortList = headA;
ListNode* longList = headB;
if(sizeA >sizeB)
{
ListNode* shortList = headB;
ListNode* longList = headA;
}
//让长链表先走gap
while(gap--)
{
longList = longList->next;
}
//两个链表在同一起跑线
while(shortList) //也可以写while(longList)
{
if(shortList == longList)
{
return shortList;
}
shortList = shortList->next;
longList = longLiat->next;
}
//链表不相交
return NULL:
}
2 环形链表(1)
思路:快慢指针,慢指针每次走一步,快指针每次走两步。如果slow和fast指向同一节点,说明该链表带环。
typedef struct ListNode ListNode
bool hasCycle (struct ListNode* head)
{
//创见快慢指针
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next)
{
if(slow == fast)
return true:
slow = slow->next;
fast = fast->next->next;
}
//链表不带环
return false;
}
在环形链表中,慢指针每次走一步,快指针每次走2,3,4,5........步,快慢指针在环形链表中一定会相遇
3 环形链表(2)
思路:快慢指针,在环里一定会相遇。
相遇点到入环节点的距离 == 头节点到入环节点的距离
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;
while(pcur != slow)
{
pcur = pcur->next;
slow = slow->next;
}
return pcur;//走到了入环节点
}
}
//链表不带环
return NULL;
}
4 链表分割
思路:创建两个链表(小链表,大链表),遍历原链表,小的尾插到小链表中,大的尾插到大链表中,大链表和小链表首尾相连
ListNode* partition(ListNode* pHead,int x)
{
ListNode* lessHead,*lessTail;
lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));
ListNode* greaterHead,*greaterTail;
greaterHead = greaterTail = (ListNode*)malloc(sizeof(ListNode));
ListNode*pcur = pHead;
//遍历原链表
while(pcur)
{
if(pcur->val < x)
{
lessTail->next = pcur;
lessTail = lessTail->next;
}
else
{
greaterTail->next = pcur;
greaterTail =greaterTai->next;
}
}
//将大链表的尾节点的next指针置为空,防止死循环
greaterTail->next = NULL;
lessTail->next = greaterHead->next;
ListNode* del = lessHead->next;
free(lessHead);
free(greaterHead);
return del;
}
5 随机链表的复制
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct Node {
int val;
struct Node* next;
struct Node* random;
} Node;
// 创建新节点
Node* buyNode(int x) {
Node* newnode = (Node*)malloc(sizeof(Node));
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;
}
}
// 设置拷贝节点的 random 指针
void setRandom(Node* head) {
Node* pcur = head;
while (pcur) {
Node* copy = pcur->next;
if (pcur->random) {
copy->random = pcur->random->next;
}
pcur = copy->next;
}
}
// 复制带 random 指针的链表
struct Node* copyRandomList(struct Node* head) {
if (head == NULL) {
return head;
}
// 在原链表基础上拷贝结点并插入在原链表中
AddNode(head);
// 设置 random
setRandom(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;
}