Linked List Cycle(find the start node)---142--找到环的起始点

题目描述:找到链表中环节点

input : 3->2->0->-4 ->2  output : 1

思路:找到头节点和相遇点到环起始点的关系,可以证明相遇点到环起始点和头节点到环起始点的距离相等
证明:头节点到环节点距离x,环节点到相遇点y,相遇点到环节点z,快指针走的距离是慢指针的2倍
S慢 = x + y + nC S快 = 2S慢 = x + y + mC = 2x + 2y + 2nC
x = (m - 2n)C - y = (m - 2n - 1)C + C - y =(m - 2n - 1)C + z
所以当相遇的时候,一个指针从头节点开始走,一个指针从相遇点开始走,再次相遇的位置就是环节点,因为他们都走过了很多圈+z的距离

#include<iostream>

using namespace std;
struct ListNode{
    int data;
    ListNode* next;
    ListNode(int x) : data(x), next(NULL){}
};
void show(ListNode* head)
{
    if(head == NULL)
    {
        cout << "NULL";
    }
    ListNode* p = head;
    while(p)
    {
        cout << p->data;
        p = p->next;
        if(p->data == head -> data)//加个判断环中的元素打印完就退出。
                break;
    }
    cout << endl;
}
ListNode* createList(int n)//尾插法创建链表
{
    ListNode* head = new ListNode(0);
    ListNode* newNode;
    ListNode* rear = head;
    for(int i = 0; i < n; i++)
    {
        int data;
        cin >> data;
        newNode = new ListNode(data);
        rear->next= newNode;
        rear = newNode;
    }
    rear->next = head->next;//让最后一个元素指向头节点,形成环
    return head->next;
}
class Solution{
public:
    ListNode* findStartNode(ListNode* head)
    {
        ListNode* fast = head, *slow = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast) break;
        }
        if(!fast || !fast->next) return NULL;
        slow = head;
        while(slow != fast)//慢指针从头开始走
        {
            slow = slow->next;
            fast = fast->next;
        }
        return fast;
    }
};
int main()
{
    ListNode* l = createList(4);
    show(l);
    Solution s;
    ListNode *l1 = s.findStartNode(l);
    show(l1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值