class Solution {
public:
ListNode* middleNode(ListNode* head) {
//快慢指针
ListNode*fast = head;
ListNode*slow = head;
while (fast != NULL&&fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
//链表元素为奇数个时,slow指向中点
//链表元素为偶数个时,slow指向两个中点的右边那个
}
return slow;
}
};
如果题目要求输出的是第一个中间节点,那么改为:
class Solution {
public:
ListNode* middleNode(ListNode* head) {
//快慢指针
ListNode*fast = head;
ListNode*slow = head;
while (fast != NULL&&fast->next != NULL&&fast->next->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
//链表元素为奇数个时,slow指向中点
//链表元素为偶数个时,slow指向两个中点的右边那个
}
return slow;
}
};
//先加个哨兵结点,快慢指针,快指针先走n步,然后快慢一起走,直到快指针走到最后
//时间复杂度O(n)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode*dummy = new ListNode(0);
dummy->next = head;
ListNode*fast = dummy, *slow = dummy;
//先让fast走n步
while (n--)
{
fast = fast->next;
}
//然后一起走
while (fast->next != NULL)
{
fast = fast->next;
slow = slow->next;
}
ListNode*temp = slow->next;
slow->next = slow->next->next;
delete temp;
temp = NULL;
return dummy->next;
}
};
class Solution {
public:
bool hasCycle(ListNode *head) {
//快慢指针,如果有圈,慢指针会被重新追上
ListNode*fast=head,*slow=head;
while(fast!=NULL&&fast->next!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)return true;
}
return false;
}
};
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
//剑指offer原题
/*
1.判断有没有环
2.求出环中的结点个数
从两个指针相遇的结点开始出发,一边继续向前移动一边计数,当再次回到这个结点时,就可以得到环中的结点个数了。
3.找环的入口结点
先定义两个指针p1、p2指向链表头结点,如果环中有n个结点,则指针p1先在链表上向前移动n步,然后两个指针均以每次1步的速度向前移动。当p2与p1相遇时,相遇结点就是入口结点。
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if (head == NULL)//链表存在
return NULL;
if (head->next == NULL)//链表非空(除了头结点外至少还有1个结点)
return NULL;
//step1
ListNode*fast = head, *slow = head;
while (fast != NULL&&fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)break;
}
if (fast != slow)return NULL;
//step2
int count = 1;
fast = fast->next;
while (fast != slow)
{
fast = fast->next;
count++;
}
//step3
ListNode*p1 = head, *p2 = head;
for (int i = 0; i < count; i++)
{
p1 = p1->next;
}
while (p1 != p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
};
首先两个链表各遍历一次,求出两个链表的长度L1,L2,然后求出两个链表的长度差diff。然后先在长链表上先走diff步,然后两个指针一起走,于是第一个相同的结点就是两个链表的交点。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int length_1 = 0, length_2 = 0;
ListNode*temp1 = headA;
ListNode*temp2 = headB;
while (temp1 != NULL)
{
temp1 = temp1->next;
length_1++;
}
while (temp2 != NULL)
{
temp2 = temp2->next;
length_2++;
}
if (length_1 > length_2)
{
int diff = length_1 - length_2;
for (int i = 0; i < diff; i++)
{
headA = headA->next;
}
while (headA != headB)
{
headA = headA->next;
headB = headB->next;
}
return headA;
}
else
{
int diff = length_2 - length_1;
for (int i = 0; i < diff; i++)
{
headB = headB->next;
}
while (headA != headB)
{
headA = headA->next;
headB = headB->next;
}
return headA;
}
}
};