思路

比较简单的思路是可以使用两个指针,一个指针向后走,每走一步,使用另外一个指针从前遍历,查看是否有重复的指针。

实现

单链表成环只有一种情况:尾部节点指向前序已有节点

代码如下:

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)
    );
}