【从零单排之微软面试100题系列】07之判断两个链表是否相交

本题目选自July大神博客系列【微软面试100题】: july大神,该系列我主要用来记录我的学习笔记。

题目描述:给出两个单向链表的头指针,判断两个链表是否相交。

 

分析思路:

如果只要判断是否相交,那么将每个链表遍历到表尾,看两个链表的表尾是不是同一个结点。因为相交的链表,最后一个结点肯定是公共的。

bool is_jointed1(Node* h1, Node* h2)
{
   if(h1 == NULL || h2 == NULL)
        return false;
    while(h1->next != NULL)
        h1 = h1->next;
     while(h2->next != NULL)
        h2 = h2->next;

     return h1 == h2;
}

此题比较简单,可再进行如下扩展:

(1)如果两个链表可能存在环,如何判断?

(2)(《剑指offer》面试题37)如何求两个链表的第一个公共结点。

对于(1),可以先判断每个链表是否存在环,分三种情况:1.都不存在环;2.只有一个存在环;3.两个都存在环。

都不存在环的情况上面已经讨论,只有一个链表存在环,说明肯定不会相交。接下来处理两个都存在环的情况。

判断存在环的代码:

Node* is_a_loop(Node* pHead)
{
    if(pHead == NULL || pHead->next ==NULL)
       return NULL;
    //定义一个快指针和慢指针,如果慢指针能够追上快指针,则存在环
    Node* p1 = pHead;
    Node* p2 = pHead->next;
    while(p2 != NULL && p2->next != NULL)
    {
       p1 = p1->next;          //一次走1步
       p2 = p2->next->next;    //一次走2步
       if( p1 == p2)
         return p1;            //返回的是环中的一个结点
    }
    return NULL;
}
假设两个链表都存在环:

bool is_jointed2(Node* h1, Node* h2)
{
    //保存两个链表中环的中的某个结点
    node* cyclic1 = is_a_loop(h1);
    node* cyclic2 = is_a_loop(h2);
    Node* p = cyclic1;
    while(1)
    {
       //在第一个环中绕一圈,看是否存在与cylic2相等的结点
       if(p == cylic2) return ture;
       //p = p->next->next;      <pre name="code" class="cpp">       p = p->next
//cylic1 = cylic1->next;
if(p == cylic1) return false;
 }
}

 

对于(2),可以根据书上的思路:首先分别遍历两个链表,得到链表的长度n1和n2。然后在长链表上先走|n1-n2|步,再同时在两个链表上遍历,找到第一个相同的结点。

//获取链表的长度
unsigned int GetListLength(Node* pHead)
{
     unsigned int nLength = 0;
     Node* pNode = pHead;
     while(pNode != NULL)
     {
          pNode = pNode->next;
          ++nLength; 
     }
     return nLength;
}

//找第一个公共结点

Node* FindFirstCommonNode(Node* pHead1, Node* pHead2)
{
     unsigned int nLen1 = GetListLength(pHead1);<pre name="code" class="cpp">     unsigned int nLen2 = GetListLength(pHead2);
     int nLenDif = nLen1 - nLen2;
    
     Node* pLong = pHead1;
     Node* pShort = pHead2;
     if(nLenDif < 0)
     {
          pLong = pHead2;
          pShort = pHead1;
          nLenDif = nLen2 - nLen1;
     }
     
     for(int i = 0; i < nLenDif; ++i)
          pLong = pLong->next;
     while(pLong != NULL && pShort != NULL && pLong != pShort)
     {
          pLong = pLong->next;
          pShort = pShort->next;
     }
    
     return pLong;
}

 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值