zoukankan      html  css  js  c++  java
  • 关于链表问题的面试题目 【微软面试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;
    }
  • 相关阅读:
    Websocket --socket.io的用法
    Vuex中mapState的用法
    vue中关于computed的一点理解
    webuploader大文件分片,多线程总结
    pdf的使用遇到的问题
    单文件WebUploader做大文件的分块和断点续传
    webUploader大文件断点续传学习心得 多文件
    iframe子页面与父页面元素的访问以及js变量的访问
    pwa 集合
    mpvue 转小程序实践总结
  • 原文地址:https://www.cnblogs.com/tractorman/p/4116758.html
Copyright © 2011-2022 走看看