链表面试题:判断两个链表是否相交

判断两个链表是否相交,若相交,求交点。(假设链表不带环)
判断两个链表是否相交,若相交,求交点。(假设链表可能带环)

采用对齐的思想。计算两个链表的长度 L1 , L2,分别用两个指针 p1 , p2 指向两个链表的头,然后将较长链表的 p1(假设为 p1)向后移动L2 - L1个节点,然后再同时向后移动p1 , p2,直到 p1 = p2。相遇的点就是相交的第一个节点。

pNode CheckCircle(pList plist)//判断链表是否有环
{
     assert(plist);
     pNode fast = plist;
     pNode slow = plist;
     if (fast && fast->next)
     {
          fast = fast->next->next;
          slow = slow->next;
          if (fast == slow)
          {
              return slow;
          }
     }
     return NULL;
}

int CircleLength(pList plist)//求环的长度
{
     assert(plist);
     pNode tmp = CheckCircle(plist);
     pNode cur = CheckCircle(plist);
     int count = 0;
     do{
          count++;
          cur = cur->next;
     } while (cur == tmp);
     return count;
}

pNode FindNode(pList plist)//碰撞点
//碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
{
     pNode tmp = CheckCircle(plist);
     pNode cur = pHead;
     while (tmp != cur)
     {
          cur = cur->next;
          tmp = tmp->next;
     }
     return tmp;
}

int CircleListLength(pList plist)//求环的长度
{
     pNode cur = pHead;
     pNode tmp = FindNode(plist);
     int count = 0;
     while (tmp != cur)
     {
          ++count;
          cur = cur->next;
     }
     return count + CircleLength(plist);
}

bool CheckNoCircleCross(pList plist1, pList plist2)//判断两个链表是否相交
{//判断两个链表的最后一个节点是否相同,如果相同,则相交
     assert(plist1);
     assert(plist2);
     while (plist1->next)
     {
          plist1 = plist1->next;
     }
     while (plist2->next)
     {
          plist2 = plist2->next;
     }
     if (plist1 == plist2)
     {
          return true;
     }
     else
          return false;
}

int ListLength(pList plist)
{
     int count = 0;
     while (plist)
     {
          ++count;
          plist = plist->next;
     }
     return count;
}

pNode FindNoCircleIntersectNode(pList plist1, pList plist2)//查找相交节点
{
     int l1 = ListLength(plist1);
     int l2 = ListLength(plist2);
     if (l1 > l2)
     {
          for (int i = 0; i < l1 - l2; ++i)
          {
              plist1 = plist1->next;
          }
     }
     else
     {
          for (int i = 0; i < l2 - l1; ++i)

          {
              plist2 = plist2->next;
          }
     }

     while (plist1 != NULL)
     {
          if (plist1 == plist2)
          {
              return plist1;
          }
          plist1 = plist1->next;
          plist2 = plist2->next;
     }
     return NULL;
}

pNode FindIntersectNode(pList plist1, pList plist2)// 查找交点(不知是否有环)
{
     if ((!CheckCircle(plist1))&&(!CheckCircle(plist2)))
     {
          FindNoCircleIntersectNode(plist1, plist2);
     }

     if (CheckCircle(plist1) && (!CheckCircle(plist2)))
     {
          return NULL;
     }

     if (CheckCircle(plist2) && (!CheckCircle(plist1)))
     {
          return NULL;
     }
     int l1 = CircleListLength(plist1);
     int l2 = CircleListLength(plist2);

     if (l1 > l2)
     {
          for (int i = 0; i < l1 - l2; ++i)
          {
              plist1 = plist1->next;
          }
     }

     if (l1 < l2)
     {
          for (int i = 0; i < l2 - l1; ++i)
          {
              plist2 = plist2->next;
          }
     }

     while (plist1)
     {
          if (plist1 == plist2)
          {
              return plist1;
          }
          plist1 = plist1->next;
          plist2 = plist2->next;
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值