Linked List Cycle II

题目: https://oj.leetcode.com/problems/linked-list-cycle-ii/指针

这一题的细节真是魔鬼。并且,好像没什么通常性,感受就是一个智力游戏
首先, 设两个指针, s(慢指针) 和 f(快指针), s每次走一步, f每次走2步.
刚开始的时候, s 和 f 都站在head, 谁先走呢? 应该是f先走. 并且 f每走完一步, 都要检查一下脚下是否是NULL,是的话,就知道没有环了, 直接退出.
好, 如今假设是有环的. 有环的话, 确定在某个时候, f会跟s重合. 可是, 问题是, 咱们要把这个"f和s是否是重合"的检查,放在哪里呢?
刚开始的时候, 我觉得放在哪里都行, 若是这道题只是问你, 有没有环, 其实放在哪里都是能够的.
可是问题是, 这道题还要求你把环的开始节点找出来, 问题就没有那么简单了.
放在哪里好呢? 既然是f先走,s后走,很天然,能够定义一个"时间单位"的概念, 在一个"时间单位"了, f先走两步,而后s走一步.
能够考虑, 把这个检查放在时间单位的后面, 也就是说, 你不能在时间单位的中间检查, 为何不能呢? 这个真的很难说...最好的办法就是, 画个图, 我想了好久才发现, 因此说,这道题的细节真是魔鬼
假设某个时间单位后, s到达了环的开始节点, 这时候, f确定在环中的某个节点X.
假设从这个X出发, 再走k步, 就能够到达环的开始节点. 那么, 咱们能够推断, 再过k个时间单位, s 和 f 就会重合. (其实, 在某个时间单位的中间, s 和 f就已经重合了, 这就是为何不能在时间单位的中间检查)
假设, 如今s和f重合了. 这时候, 咱们再设一个指针m站在head. 而后, 神奇的事情就要发生了.
咱们从新定义一个时间单位为"让m走一步, s再走一步"
你会发现, 通过若干个时间单位之后, m和s就会重合, 并且重合的那一点, 竟然就是环的开始.
要说明为何, 文字真的很吃力, 最好的办法就是画图, 摸清楚各个阶段里面, 各个位置, 以及各个位置之间的距离关系code

如下是代码:游戏

/**
 * 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) return NULL;
		
	  ListNode * s = head;	    
	  ListNode * f = head;
	  ListNode * m = head;	 

	  while(1) {
		f=f->next;
		if (f == NULL) return NULL;
		f=f->next;
		if (f == NULL) return NULL;
		s=s->next;
		if (f == s) break;
	  }
	  
	  while (1) {
		if (m == s) return m;
		m = m->next;
		s = s->next;
	  }
	}
	
};
相关文章
相关标签/搜索