快慢指针(4个链表题)

在这里插入图片描述

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;

		}


	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值