[leetcode] 142.Linked List Cycle II

题目:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Follow up:
Can you solve it without using extra space?
题意:
给定一个链表,如果有环的话,找出环的开始节点,否则返回NULL。
思路:
首先来确定是否存在环,依旧使用一快一慢两个指示器,一个每次往前走两步,一个每次往前走一步,如果遇到NULL了,说明能够访问到链表的结尾,所以不存在环。否则的话两者一定在环中相遇。

  1. 假设慢节点走了k步到达环的入口处,那么快结点此时已经在环中走了k步,假设环的长度是length,并且假设k = m*length + n,那么此时快结点离环的入口节点的距离是n。接下来慢节点也会进入环,并且按照运动方向,此时快结点与慢节点其实相距是length - n的长度,接下来就是追逐戏,快结点去追慢节点,慢节点每走一步,快结点会走两步,所以它们之间的距离就会少一,所以追逐了length - n步之后,它们就会在环中相遇了。此时这两个节点离环的入口位置距离是n。而我们知道从链表的头结点倒环的入口距离是k,而k = m*length + n,那么此时我们让快结点从链表头结点开始,但是此时快结点变成跟慢节点一样的速度,那么两个节点一定会在环的入口处相遇,因为快结点到达入口时,慢节点正好在里面绕了m圈后,又走了n步,正好就在环的入口处。
    以上,代码如下:
/**
 1. Definition for singly-linked list.
 2. struct ListNode {
 3.     int val;
 4.     ListNode *next;
 5.     ListNode(int x) : val(x), next(NULL) {}
 6. };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head == NULL || head->next == NULL)return NULL;
        ListNode *node1 = head->next, *node2 = head->next->next;
        while(node2 != NULL && node1 != node2) {
            node1 = node1->next;
            node2 = node2->next;
            if(node2 == NULL)break;
            node2 = node2->next;
        }
        if(node2 == NULL)return NULL;
        ListNode *h2 = head->next;
        node1 = node1->next;
        while(node1 != node2) {
            node1 = node1->next;
            h2 = h2->next;
        }
        ListNode *h1 = head;
        while(h1 != h2) {
            h1 = h1->next;
            h2 = h2->next;
        }
        return h1;
    }
};

2.思路二,同样是快慢节点先在环中相遇。然后我们找出环的长度,让慢节点不动,快结点继续一步一步的走,直到快结点再次走到慢节点所在的位置,统计出长度length。接下来,让先行节点先走length,然后后行节点也开始往前走,所以当两者再次相遇的时候,正好是在环的入口处。因为先行节点正好多走了一个环的长度。
以上。
代码如下:

/**
 * 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) {
        if(head == NULL || head->next == NULL)return NULL;
        ListNode *node1 = head->next, *node2 = head->next->next;
        while(node2 != NULL && node1 != node2) {
            node1 = node1->next;
            node2 = node2->next;
            if(node2 == NULL)break;
            node2 = node2->next;
        }
        if(node2 == NULL)return NULL;
        ListNode *h2 = head->next;
        node1 = node1->next;
        while(node1 != node2) {
            node1 = node1->next;
            h2 = h2->next;
        }
        ListNode *h1 = head;
        while(h1 != h2) {
            h1 = h1->next;
            h2 = h2->next;
        }
        return h1;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值