这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战
常用方法
- 画图理解链表题目
- 善用双指针
- 设置虚拟头结点解决删除head节点的问题
双指针相关题目
- 倒数第k个节点相关、取得/删除倒数第k个节点、旋转链表
- 判断链表是否有环
- 两链表公共节点
题目解法记录
LeetCode 160 两链表公共节点
普通思路
分别遍历两链表计算长度m、n,长的链表先走m-n步,然后一起走,并比较是否相等
/*
* @lc app=leetcode id=160 lang=cpp
*
* [160] Intersection of Two Linked Lists
*/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *p = headA;
ListNode *q = headB;
int i = 0;
int j = 0;
while (p!= nullptr)
{
p = p->next;
i++;
}
while (q != nullptr)
{
q = q->next;
j++;
}
p = headA;
q = headB;
while (i > j)
{
p = p->next;
i--;
}
while (i < j)
{
q = q->next;
j--;
}
while (p != nullptr && q != nullptr)
{
if (p == q)
{
return p;
}
p = p->next;
q = q->next;
}
return nullptr;
}
};
双指针思路
使用两个指针遍历两链表,当a链表走到头时,开始转到b链表的头,b链表同理,两指针相等时就取到了共同节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *a,*b;
a = headA;
b = headB;
while(a != b){
if(!a) a = headB;
else a = a->next;
if(!b) b = headA;
else b = b->next;
}
return a;
}
};
LeetCode 142 确定有环链表的节点
算法
- 使用快慢指针往前走,直到快指针和慢指针相遇
- 然后使用一个指针从头走,慢指针继续走,两指针相遇,则为第一个环节点
原理
- 首先分析快慢指针相遇时走过的路程,设起点为a,第一个环节点为b,相遇点为c,a->b=x
- 设慢指针走到b点时,快指针走到c1,则此时c1->b长度等于b->c,设为y,此时慢指针走了x步,则快指针走了2*x步。可得从b点开始绕环走x步,最后距离b点为y,那么从超出b点y步的位置开始走x步,则最后的点就是b点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *dummy = new ListNode(-1);
dummy->next = head;
ListNode *slow = dummy, *fast = dummy;
bool flag = false;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)
{
flag = true;
break;
}
}
if (!flag)
return nullptr;
ListNode *result = dummy;
while (result != slow)
{
result = result->next;
slow = slow->next;
}
return result;
}
};