题目:
Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
这道题刚开始没想出来,看了分析,思考程度需要提高。
分析: 链表的交叉只有 Y 型,没有 X 型。 如果链表里有cycle, 那遍历会一直进行下去。 如果没有,就会出现None
如何知道遍历会不会循环进行下去? 设一个fast和slow,fast 2步遍历,slow 1步遍历。如果循环遍历的话,他们俩就会碰到。
刚开始写的代码错误比较多。开始先判断link是空和只有1个node. 先遍历一步,再做while。 while 的判断句也写错了。这里思路挺乱的
class Solution:
# @param head, a ListNode
# @return a boolean
def hasCycle(self, head):
if head==None:
return False
if head.next==None:
return False
fast,slow = head,head
fast,slow = fast.next.next, slow.next
while fast!=None or fast.next!=None:
fast,slow = fast.next.next,slow.next
if fast==slow:
return True
return False
现在重新理清思路:
1. 判断链表是否为空。
2. 起始条件? 终止条件? 终止条件和初始条件重叠时?
* 起始条件: fast 和 slow 都设置成head
* 终止条件: (1) 有cycle, fast==slow
(2) 没有cycle, fast 会先到头。
因为fast 是两步跳,所以还要区分:
((1)) fast 跳到最后一个None
((2)) fast 跳到倒数第2个, 即 fast.next ==None
只要这两个都不是,就可以。 所以是 ( !A and !B )
到这时,就说明链表遍历到头了, 没有cycle
* 终止条件和初始条件重叠?: 也即链表个数非常少
(1) 链表个数为1,即一个Node+一个None, 终止条件成立
(2) 链表个数为2, 3个Node, 最后一个为None. 也成立
3. 最后划简。 发现第1步也能划归到第2步里
所以最后只有第2步了
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# @param head, a ListNode
# @return a boolean
def hasCycle(self, head):
fast,slow = head,head
while fast!=None and fast.next!=None:
fast,slow = fast.next.next,slow.next
if fast==slow:
return True
return False
C++ :
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* fast;
ListNode* slow;
fast = head;
slow = head;
while (fast!=NULL and fast->next!=NULL){
fast = fast->next->next;
slow = slow->next;
if (fast==slow){
return true;
}
}
return false;
}
};
总结:
1. 有些case, 能划分到后面的case里,就要划简。 一切从简。
2. 思考链表问题的时候,可以把链表的最后加上一个新的结点 None
3. 做罗辑判断时,要搞清楚 and, or, not
编程语言: python 中的空是None, c++ 中的空是NULL