您的位置:首页 > 职场人生

判断两个链表是否相交 【微软面试100题 第七题】

2014-10-27 16:15 351 查看
题目要求:

  给出两个单向链表的头指针,比如h1和h2,判断两个链表是否相交。

题目分析:

  1.边界检查:是否为NULL

  2.是否有环:

    i).h1和h2都没有环,则如果h1和h2的最后一个结点时同一个结点,则相交;

    ii).一个有环,一个无环,则肯定不相交;

    iii).都有环,则如果h1的环中的一个结点走一圈可以达到h2环中的一个结点,则相交;

  3.判断单链表是否有环方法:

    方法1 使用反转指针的方法:每过一个结点就把该结点的指针反向。当存在环时,最后指针肯定会定位到链表头部。如果到最后都没有到头部,则说明链表不存在循环。

    方法2 快慢指针法:快指针pf每次移动2个结点,慢指针ps每次移动1个结点,如果快指针能够追上慢指针,则有环。

    方法1和方法2都可以通过画图来理解。

[b]

#include <iostream>

using namespace std;

typedef struct Node
{
struct Node *next;
int data;
}Node;
void initNode(Node **h1,Node **h2);
bool detect(Node *head1, Node *head2);
void initNode1(Node **h1,Node **h2);
void initNode2(Node **h1,Node **h2);
int main(void)
{
Node *h1,*h2;
//initNode(&h1,&h2);
//initNode1(&h1,&h2);
initNode2(&h1,&h2);
if(detect(h1,h2))
cout << "相交" << endl;
else
cout << "不相交" << endl;
return 0;
}
//无环相交
void initNode(Node **h1,Node **h2)
{
Node *tmp = new Node;
tmp->data = 1;
*h1 = tmp;

tmp = new Node;
(*h1)->next = tmp;
tmp->data = 2;
*h2 = tmp;
tmp->next = NULL;
}
//无环不相交
void initNode1(Node **h1,Node **h2)
{
Node *tmp = new Node;
tmp->data = 1;
*h1 = tmp;

tmp = new Node;
(*h1)->next = tmp;
tmp->data = 2;
tmp->next = NULL;

tmp = new Node;
*h2= tmp;
tmp->data = 3;
tmp->next = NULL;
}
//有环相交
void initNode2(Node **h1,Node **h2)
{
Node *tmp = new Node;
tmp->data = 1;
*h1 = tmp;

tmp = new Node;
(*h1)->next = tmp;
tmp->data = 2;
*h2 = tmp;
tmp->next = *h1;
}
bool isCircle(Node *h,Node **circleNode,Node **lastNode)
{
Node *ps = h,*pf = h;
while(1)
{
if(pf && pf->next)
{
pf=pf->next->next;
}
else
{
ps = h;
while(ps->next!=NULL)
ps = ps->next;
*lastNode = ps;
return false;
}

ps=ps->next;

if(ps==pf)
{
break;
}
}

//没有return false则证明存在环
//分别从相遇点和第一个节点出发,都是步长为1的指针,当相遇位置即为环首的位置。
//具体证明见图
Node *p=h;
while(p!=ps)
{
p=p->next;
ps=ps->next;
}
*circleNode = ps;
return true;
}
bool detect(Node *head1, Node *head2)
{
if(head1==NULL || head2==NULL)
return false;

Node *circleNode1;//链表1的入环点
Node *circleNode2;//链表2的入环点
Node *lastNode1;//链表1的最后一个结点(无环)
Node *lastNode2;//链表2的最后一个结点(无环)

bool isCircle1 = isCircle(head1,&circleNode1,&lastNode1);
bool isCircle2 = isCircle(head2,&circleNode2,&lastNode2);

//一个有环,一个无环
if(isCircle1 != isCircle2)
return false ;

//两个都无环,判断最后一个节点是否相等
else if (!isCircle1 && !isCircle2)
{
return lastNode1 == lastNode2;
}

//两个都有环,判断环里的节点是否能到达另一个链表环里的节点
else
{
Node *temp = circleNode1->next;
while(temp != circleNode1)
{
if(temp == circleNode2)
return true ;
temp = temp->next;
}
return false ;
}
return false ;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: