To_10_r_100_7---关于链表的环以及相交问题的整理

来源:互联网 发布:夏普百视通网络电视 编辑:程序博客网 时间:2024/06/05 22:45

!参考网络资料和自己的理解整理而得

题目:

1. 如何判断是否有环?

答:如果有两个头结点指针,一个走的快,一个走的慢,那么若干步以后,快的指针总会超过慢的指针一圈而相遇。

       感性理解:就像是时钟的分针以及秒针一样。

       定量分析:当fast与slow相遇时,show肯定没有走完链表,而fast已经在还里走了n(n>= 1)圈。假设slow走了s步,那么fast走了2s步。fast的步数还等于s走的加上环里转的n圈,所以有:2s = s + nr。因此,s = nr。


2. 如何计算环的长度?

答:第一次相遇(超一圈)时开始计数,第二次相遇时停止计数。

       定量分析:当fast与slow第一次相遇时,s=nr。当fast与slow第二次相遇时,s'=(n+1)r(即一个走多r,一个走多2r)。所以可以得到r=s-s'。


3. 如何判断环的入口点?

答:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
       定量分析:设整个链表长为L,入口据相遇点X,起点到入口的距离为a。因为slow指针并没有走完一圈,所以:a + x = s,代入第一步的结果,有:a + x = s。因此,起点 至 a点 从起点共走了a步到达a点;碰撞点 至 a点 从碰撞点共走了a步到达2a+x=2s-x=nr+s-x=nr+a<==>a点;此时,两个指针重合。

4. 如何判断两个链表(不带环)是否相交?

答:

方法一:将其中的一个链表首尾相连,然后判断另一个链表是否带环即可。

方法二:同时遍历两条链表,并查看结点是否重合。


5. 如何判断两个链表(带环)是否相交?

答:从相遇点开始利用一个记录指针在其中一个链表环内走一圈,看是否会与另外一个链表的某个结点重合。


C++代码:

#include <iostream>
using namespace std;

struct Node{
 int data;
 Node* next;
};

Node* testCylic(Node* h1){
 Node *p1 = h1, *p2 = h1;
 while (p1 != NULL&&p2->next != NULL){
  p1 = p1->next;
  p2 = p2->next->next;
  if (p1 == p2){
   return p1;
  }
 }
 return NULL;
}

int loopLength(Node* h1){
 Node *p1 = h1, *p2 = h1;
 bool first = true;
 int length = 0;
 while (p1 != NULL&&p2->next != NULL){
  p1 = p1->next;
  p2 = p2->next->next;
  if (p1 == p2 && first){
   first = false;
  }

  if (p1 == p2&& !first)
   break;

  if (!first)
   length++;
 }
 return length;
}

Node* findLoopEntrance(Node* h1){
 Node* p1 = testCylic(h1);
 if (p1 == NULL || h1==NULL)
  return NULL;
 Node* p2 = h1;
 while (p1 != p2){
  p1 = p1->next;
  p2 = p2->next;
 }
 return p1;
}

// if there is no cycle.
bool isJoinedSimple(Node *h1, Node *h2){
 Node* p1 = h1;
 Node* p2 = h2;
 while (p1->next != NULL)
  p1 = p1->next;
 while (p2->next != NULL)
  p2 = p2->next;
 return p1 == p2;
}

// if there could exist cycle
bool isJoined(Node *h1, Node *h2){
 Node* cylic1 = testCylic(h1);
 Node* cylic2 = testCylic(h2);
 if (cylic1 == NULL && cylic2 == NULL)
  return isJoinedSimple(h1, h2);
 if ((cylic1 == NULL&&cylic2 != NULL) || (cylic1 != NULL&&cylic2 == NULL))
  return false;
 Node* p1 = cylic1;
 while (1){
  if (p1 == cylic2 || p1 == cylic2->next)//The node in link1 is equal to cylic2
   return true;
  p1 = p1->next->next;
  cylic1 = cylic1->next;
  if (p1 == cylic1) //Traverse all the nodes in link1
   return false;
 }
}



0 0
原创粉丝点击