第一题 相交链表
题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists/description/
分析:
相交链表就是找到相交的那个节点,就存在相交和不相交两种情况。
不相交,返回NULL即可。相交,则要判定相交的点,首先我们要确定不能使用值来找,因为,链表的值都是一样的话就无法找到。我们可以先计算两个链表的长度,长的先走abs(lenA-lenB)步,这样就能找到相交的点。
画图分析:
完整代码:
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode* curA = headA;
struct ListNode* curB = headB;
int lenA = 1;
int lenB = 1;
//链表不为空时往后走
while(curA->next)
{
curA=curA->next;
++lenA;
}
while(curB->next)
{
curB=curB->next;
++lenB;
}
//如果不相交返回NULL
if(curA!=curB)
{
return NULL;
}
//相交
//计算长链表多先走的步
int gap = abs(lenA - lenB);
struct ListNode* Longlist = headA;
struct ListNode* Shortlist = headB;
if(lenA < lenB)
{
Longlist = headB;
Shortlist = headA;
}
//长的先走
while(gap--)
{
Longlist = Longlist->next;
}
//同时走找交点
while(Longlist != Shortlist)
{
Longlist = Longlist->next;
Shortlist = Shortlist->next;
}
return Longlist;
}
第二题 链表分割
完整代码:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
// write code here
struct ListNode* lhead,*ltail,*ghead,*gtail;
lhead = ltail = (struct ListNode*)malloc(sizeof(struct ListNode));
ghead = gtail = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* cur = pHead;
while(cur)
{
if(cur->val<x)
{
ltail->next = cur;
ltail = ltail->next;
}
else
{
gtail->next = cur;
gtail = gtail->next;
}
cur = cur->next;
}
ltail->next = ghead->next;
//不空可能出现环
gtail->next = NULL;
struct ListNode* head = lhead->next;
free(lhead);
free(ghead);
return head;
}
};
第三题 环形链表
题目链接:https://leetcode.cn/problems/linked-list-cycle/description/
分析:环形链表就是看尾节点的next是否指向链表中的节点,所以可以看成是追击问题,定义slow,fast两个指针,当二者能相遇就是有环,否则无环。
画图分析:
完整代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
struct ListNode * slow = head,* fast = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(slow == fast)
return true;
}
return false;
}
第四题 环形链表(2)
分析:在判断环的基础上返回入环的第一个节点,也就是相遇的点;依然使用快慢指针,但是在相遇点多层判断(head 是否和 meet 相等)。
画图分析;
完整代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *slow = head,* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
//相遇
if(slow == fast)
{
struct ListNode* meet = slow;
while(head != meet)
{
meet = meet->next;
head = head->next;
}
return meet;
}
}
return NULL;
}
第五题 复制带随机指针的链表
题目链接:
分析:
完整代码:
/**
* Definition for a Node.
* struct Node {
* int val;
* struct Node *next;
* struct Node *random;
* };
*/
struct Node* copyRandomList(struct Node* head) {
// 1.拷贝链表,并插入到原节点的后面
struct Node* cur = head;
while(cur)
{
struct Node* next = cur->next;
struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
copy->val = cur->val;
// 插入
cur->next = copy;
copy->next = next;
// 迭代往下走
cur = next;
}
// 2.置拷贝节点的random
cur = head;
while(cur)
{
struct Node* copy = cur->next;
if(cur->random != NULL)
copy->random = cur->random->next;
else
copy->random = NULL;
cur = copy->next;
}
// 3.解拷贝节点,链接拷贝节点
struct Node* copyHead = NULL, *copyTail = NULL;
cur = head;
while(cur)
{
struct Node* copy = cur->next;
struct Node* next = copy->next;
// copy解下来尾插
if(copyTail == NULL)
{
copyHead = copyTail = copy;
}
else
{
copyTail->next = copy;
copyTail = copy;
}
cur->next = next;
cur = next;
}
return copyHead;
}