关闭

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

标签: 微软面试题算法笔记
140人阅读 评论(0) 收藏 举报
分类:
本题目选自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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:4227次
    • 积分:226
    • 等级:
    • 排名:千里之外
    • 原创:20篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档
    最新评论