问题:
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
提示:
- 链表中节点的数目范围是
[0,
]
<= Node.val <=
示例1:
输入:head = [3,2,0,-4] 输出:true
示例2:
输入:head = [1,2] 输出:true
示例3:
输入:head = [1] 输出:false
解答:
方法一:先反转再比较
对链表进行反转,若链表中存在环,则反转后的链表的头和原链表的头是同一个,利用这个性质验证链表中是否存在环。
若链表中存在部分环,则链表中非环部分会被反转两次,最终头节点回到原来的头节点上;
若链表整个为一个环,则链表中的头肯定和原来的头一样。
代码如下:
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* reverseList(ListNode* head) {
ListNode* newHead = nullptr;
while (head != nullptr) {
ListNode* temp = head->next;
head->next = newHead;
newHead = head;
head = temp;
}
return newHead;
}
bool hasCycle(ListNode *head) {
ListNode *newHead = reverseList(head);
if (head != nullptr && head->next != nullptr && head == newHead)
return true;
return false;
}
方法二:快慢指针
我们定义两个指针,一快一满。慢指针每次只移动一步,而快指针每次移动两步。初始时,慢指针在位置 head,而快指针在位置 head.next。这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。否则快指针将到达链表尾部,该链表不为环形链表。
代码如下:
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
bool hasCycle(ListNode* head) {
if (head == nullptr || head->next == nullptr) {
return false;
}
ListNode* slow = head;
ListNode* fast = head->next;
while (slow != fast) {
if (fast == nullptr || fast->next == nullptr) {
return false;
}
slow = slow->next;
fast = fast->next->next;
}
return true;
}