关于链表问题的面试题目 【微软面试100题 第七十七题】

题目要求:

  1.给定一个单链表,检测是否有环;

  2.判断两个无环单链表是否有交点;

  3.给定两个单链表,检测两个链表是否有交点;

  4.给定单链表,如果有环的话请返回从头结点进入环的第一个结点;

  5.只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点;

  6.只给定单链表中某个结点p(非空结点),在p前面插入一个结点。

题目分析:

  问题1:

    方法1 反转链表:每过一个节点就把该节点的指针反向。当有环的时候,最后指针会定位到链表的头部,如果到最后,都没有再到头部,那说明链表不存在循环。(但是会破换链表)

    方法2 快慢指针:快指针pf(f就是fast的缩写)每次移动2个节点,慢指针ps(s为slow的缩写)每次移动1个节点,如果快指针能够追上慢指针,那就说明其中有一个环,否则不存在环。

  问题2:

    方法1 把其中一条链表尾部指到首部。然后判断另外一条链表是否有环,如果有环,则说明两链表相交。

    方法2 找到两个链表的尾结点,进行比较,如果两个尾结点相等则相交;

  问题3:   

    先判断两个链表是否带环;----问题1
      i).如果两个都不带环,可以用:判断两个无环单链表是否有交点。----问题2
      ii).两个都带环:找到两个入环点r1,r2,环1的入环点为r1,从r1开始遍历一圈,每个结点如r2比较。---问题3
      iii).一个带环一个不带环,则肯定不相交。
  问题4:
    用问题1的方法判断是否有环,再采用下图的方法找入口点。
 
  问题5:
 
  问题6:
    和问题5的方法相似,在p结点之后插入一个结点,把该结点的值赋值为p结点的值,p结点的值改为插入结点的值。

代码实现:

问题代码1:

#include <iostream>
#include <stack>

using namespace std;

typedef struct ListNode
{
    struct ListNode *next;
    int data;
}ListNode;

void InitList(ListNode **head1);
bool HasLoop(ListNode *llist);

int main(void)
{
    ListNode *h;
    
    InitList(&h);
    if(HasLoop(h))
        cout << "有环" << endl;
    else
        cout << "无环" << endl;

    h = NULL;
    if(HasLoop(h))
        cout << "有环" << endl;
    else
        cout << "无环" << endl;

    return 0;
}
//     ------------
//    |/        /|
//head:1-->5-->9-->
void InitList(ListNode **head)
{
    ListNode *tmp = new ListNode;
    tmp->data = 1;
    *head = tmp;

    tmp = new ListNode;
    tmp->data = 5;
    (*head)->next = tmp;

    ListNode *tmp1 = new ListNode;
    tmp1->data = 9;
    tmp1->next = *head;
    tmp->next = tmp1;
}
bool HasLoop(ListNode *llist)
{
     ListNode *pf=llist;
     ListNode *ps=llist;
    
     while(true)
     {
          if(pf && pf->next)
          {
               pf=pf->next->next;
          }
          else
               return false;
         
          ps=ps->next;
         
          if(ps==pf)
          {
               break;
          }
     }
    
     return true;
}

问题代码2:

#include <iostream>
#include <stack>

using namespace std;

typedef struct ListNode
{
    struct ListNode *next;
    int data;
}ListNode;

void InitList(ListNode **head1,ListNode **head2);
bool IsTwoListHasCommonNode(ListNode *head1,ListNode *head2);

int main(void)
{
    ListNode *h1,*h2;
    
    InitList(&h1,&h2);
    if(IsTwoListHasCommonNode(h1,h2))
        cout << "相交" << endl;
    else
        cout << "不相交" << endl;
    
    h2=NULL;
    if(IsTwoListHasCommonNode(h1,h2))
        cout << "相交" << endl;
    else
        cout << "不相交" << endl;
    return 0;
}
//head1:1-->5-->9-->NULL
//head1:5-->9-->NULL
void InitList(ListNode **head1,ListNode **head2)
{
    ListNode *tmp = new ListNode;
    tmp->data = 1;
    *head1 = tmp;

    tmp = new ListNode;
    tmp->data = 5;
    *head2 = tmp;
    (*head1)->next = tmp;

    ListNode *tmp1 = new ListNode;
    tmp1->data = 9;
    tmp1->next = NULL;
    tmp->next = tmp1;
}
ListNode *GotoLastNode(ListNode *head)
{
    while(head->next)
        head = head->next;
    return head;
}
bool IsTwoListHasCommonNode(ListNode *head1,ListNode *head2)
{
    if(head1==NULL || head2==NULL)
        return false;

    ListNode *h1 = GotoLastNode(head1);
    ListNode *h2 = GotoLastNode(head2);
    
    if(h1==h2)
        return true;
    else
        return false;
}

问题代码3:

#include <iostream>
#include <stack>

using namespace std;

typedef struct ListNode
{
    struct ListNode *next;
    int data;
}ListNode;

void InitList(ListNode **head1,ListNode **head2);
bool detect(ListNode *head1, ListNode *head2);
int main(void)
{
    ListNode *h1,*h2;
    
    InitList(&h1,&h2);
    if(detect(h1,h2))
        cout << "相交" << endl;
    else
        cout << "不相交" << endl;
    
    h2=NULL;
    if(detect(h1,h2))
        cout << "相交" << endl;
    else
        cout << "不相交" << endl;
    return 0;
}
//head1:1-->5-->9-->NULL
//head1:5-->9-->NULL
void InitList(ListNode **head1,ListNode **head2)
{
    ListNode *tmp = new ListNode;
    tmp->data = 1;
    *head1 = tmp;

    tmp = new ListNode;
    tmp->data = 5;
    *head2 = tmp;
    (*head1)->next = tmp;

    ListNode *tmp1 = new ListNode;
    tmp1->data = 9;
    tmp1->next = NULL;
    tmp->next = tmp1;
}
ListNode *GotoLastNode(ListNode *head)
{
    while(head->next)
        head = head->next;
    return head;
}
bool HasLoop(ListNode *llist,ListNode **circleNode)
{
     ListNode *pf=llist;
     ListNode *ps=llist;
    
     while(true)
     {
          if(pf && pf->next)
          {
               pf=pf->next->next;
          }
          else
               return false;
         
          ps=ps->next;
         
          if(ps==pf)
          {
               break;
          }
     }
    
     //找入环点
     ListNode *p=llist;
     while(p!=ps)
     {
          p=p->next;
          ps=ps->next;
     }
     *circleNode = p;

     return true;
}
bool detect(ListNode *head1, ListNode *head2)
{
    if(head1==NULL || head2==NULL)
        return false;
    ListNode* circleNode1;//链表1的入环点
    ListNode* circleNode2;//链表2的入环点
    ListNode* lastNode1 = GotoLastNode(head1);//链表1的最后一个结点(无环)
    ListNode* lastNode2 = GotoLastNode(head2);//链表2的最后一个结点(无环)

    bool isCircle1 = HasLoop(head1,&circleNode1);
    bool isCircle2 = HasLoop(head2,&circleNode2);
    //一个有环,一个无环
    if(isCircle1 != isCircle2)
        return false ;
    //两个都无环,判断最后一个节点是否相等
    else if (!isCircle1 && !isCircle2)
    {
        return lastNode1 == lastNode2;
    }
    //两个都有环,判断环里的节点是否能到达另一个链表环里的节点
    else
    {
        ListNode * temp = circleNode1->next; 
        while(temp != circleNode1)
        {
            if(temp == circleNode2)
                return true ;
            temp = temp->next;
        }
        if(temp == circleNode2)
                return true ;
        return false ;
    }
    return false ;
}

问题代码4:

#include <iostream>
#include <stack>

using namespace std;

typedef struct ListNode
{
    struct ListNode *next;
    int data;
}ListNode;

void InitList(ListNode **head1);
bool HasLoop(ListNode *llist,ListNode **circleNode);

int main(void)
{
    ListNode *h1,*circleNode;
    
    InitList(&h1);
    if(HasLoop(h1,&circleNode))
        cout << "有环,并且第一个入环点为:" << circleNode->data << endl;
    else
        cout << "无环" << endl;
    
    return 0;
}
//          _____
//         |/ /|
//head1:1-->5-->9
void InitList(ListNode **head1)
{
    ListNode *tmp = new ListNode;
    tmp->data = 1;
    *head1 = tmp;

    tmp = new ListNode;
    tmp->data = 5;
    (*head1)->next = tmp;

    ListNode *tmp1 = new ListNode;
    tmp1->data = 9;
    tmp1->next = tmp;
    tmp->next = tmp1;
}
bool HasLoop(ListNode *llist,ListNode **circleNode)
{
     ListNode *pf=llist;
     ListNode *ps=llist;
    
     while(true)
     {
          if(pf && pf->next)
          {
               pf=pf->next->next;
          }
          else
               return false;
         
          ps=ps->next;
         
          if(ps==pf)
          {
               break;
          }
     }
    
     //找入环点
     ListNode *p=llist;
     while(p!=ps)
     {
          p=p->next;
          ps=ps->next;
     }
     *circleNode = p;

     return true;
}
原文地址:https://www.cnblogs.com/tractorman/p/4116758.html