1. 程式人生 > >判斷單鏈表是否帶環?若帶環,求環的長度?求環的入口點?

判斷單鏈表是否帶環?若帶環,求環的長度?求環的入口點?

判斷單鏈表是否帶環?若帶環,求環的長度?求環的入口點?

這道題有三問,是否帶環?環的長度?環的入口點?

1.單鏈表是否帶環?

思路分析:怎麼樣才算帶環呢?我們細想,如果一個單鏈錶帶環的話,那麼它怎麼走都走不出來的,而如果不帶環的話,那麼一定會走到NULL的。
設定快慢指標,剛開始都指向連結串列的起始位置,快指標一次走兩步,慢指標一次走一步,如果兩個指標相遇,則帶環;若快指標走到NULL,則不帶環。

程式碼:

Node *IsCircleList(Node *list)
{
 Node *fast = list;
 Node *slow = list;
 if (list == NULL || list->next == NULL)
 {
  return NULL;
 }
 while (fast&&fast->next)
 {
  fast = fast->next->next;//快指標一次走兩步
  slow = slow->next;//慢指標一次走一步
 }
 if (fast == slow)
 {
  return fast;//如果相等,返回相遇點
 }
}

2.求環的長度?

思路分析:當我們已經知道了這個連結串列是帶環的,那麼環的長度又該如何求呢?
首先我們上一步已經確定這個連結串列帶環,並且找到了快慢指標的相遇點,那麼我們就可以從相遇點開始再走一圈,每走一步計數,當再次走到相遇點的時候,便求出了環的長度。

程式碼:

int GetCircleLen(Node *list)
{
 Node *p = IsCircleList(list);
 int count = 0;
 if (p != NULL)//帶環
 {
  while (p->next != p)
  {
   count++;
   p = p->next;
  }
  count++;//加上最後一個結點
 }
 return count;
}

3.求環的入口點

思路分析:這一步個人覺得有點變態,因為需要用到數學推導證明。我在這裡以圖的形式分析比較清楚一下,如下圖:

在這裡插入圖片描述
程式碼:

Node *EnterNode(Node *list)
{
 Node *node = IsCircleList(list);
 Node *first = list;
 if (node != NULL)//帶環
 {
  while (node != first)
  {
   node = node->next;
   first = first->next;
  }
 }
 return node;
}