思路
比较简单的思路是可以使用两个指针,一个指针向后走,每走一步,使用另外一个指针从前遍历,查看是否有重复的指针。
实现
单链表成环只有一种情况:尾部节点指向前序已有节点
代码如下:
struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: bool hasCycle(ListNode* head) { if (!head) return false; // 声明必要变量 ListNode* bak = head; ListNode* scan = head; // head != nullptr while (bak->next) { // 扫描链表 if (bak == bak->next) return true; /* 内循环终止条件:1. scan == head; 2. scan = head.next; return true */ scan = head; while (scan != bak) { if (scan == bak->next) return true; scan = scan->next; } bak = bak->next; } return false; } };
测试
附上测试代码(gtest):
TEST(List, ListCircle ) { // 无循环链表 ListNode noCircle(10); ListNode noCircle1(10); ListNode noCircle2(10); ListNode noCircle3(10); noCircle.next = &noCircle1; noCircle1.next = &noCircle2; noCircle2.next = &noCircle3; // 有循环链表 ListNode hasCircle(10); ListNode hasCircle1(10); ListNode hasCircle2(10); hasCircle.next = &hasCircle1; hasCircle1.next = &hasCircle2; hasCircle2.next = &hasCircle1; // 创建检测对象 Solution sol; EXPECT_FALSE(sol.hasCycle(&noCircle) ); EXPECT_TRUE(sol.hasCycle(&hasCircle) ); }