zoukankan      html  css  js  c++  java
  • 判断两个链表是否相交 【微软面试100题 第七题】

    题目要求:

      给出两个单向链表的头指针,比如h1和h2,判断两个链表是否相交。

    题目分析:

      1.边界检查:是否为NULL

      2.是否有环:

        i).h1和h2都没有环,则如果h1和h2的最后一个结点时同一个结点,则相交;

        ii).一个有环,一个无环,则肯定不相交;

        iii).都有环,则如果h1的环中的一个结点走一圈可以达到h2环中的一个结点,则相交;

      3.判断单链表是否有环方法:

        方法1 使用反转指针的方法:每过一个结点就把该结点的指针反向。当存在环时,最后指针肯定会定位到链表头部。如果到最后都没有到头部,则说明链表不存在循环。

        方法2 快慢指针法:快指针pf每次移动2个结点,慢指针ps每次移动1个结点,如果快指针能够追上慢指针,则有环。

        方法1和方法2都可以通过画图来理解。

    代码:

    #include <iostream>
    
    using namespace std;
    
    typedef struct Node
    {
        struct Node *next;
        int data;
    }Node;
    void initNode(Node **h1,Node **h2);
    bool detect(Node *head1, Node *head2);
    void initNode1(Node **h1,Node **h2);
    void initNode2(Node **h1,Node **h2);
    int main(void)
    {
        Node *h1,*h2;
        //initNode(&h1,&h2);
        //initNode1(&h1,&h2);
        initNode2(&h1,&h2);
        if(detect(h1,h2))
            cout << "相交" << endl;
        else
            cout << "不相交" << endl;
        return 0;
    }
    //无环相交
    void initNode(Node **h1,Node **h2)
    {
        Node *tmp = new Node;
        tmp->data = 1;
        *h1 = tmp;
    
        tmp = new Node;
        (*h1)->next = tmp;
        tmp->data = 2;
        *h2 = tmp;
        tmp->next = NULL;
    }
    //无环不相交
    void initNode1(Node **h1,Node **h2)
    {
        Node *tmp = new Node;
        tmp->data = 1;
        *h1 = tmp;
    
        tmp = new Node;
        (*h1)->next = tmp;
        tmp->data = 2;
        tmp->next = NULL;
    
        tmp = new Node;
        *h2= tmp;
        tmp->data = 3;
        tmp->next = NULL;
    }
    //有环相交
    void initNode2(Node **h1,Node **h2)
    {
        Node *tmp = new Node;
        tmp->data = 1;
        *h1 = tmp;
    
        tmp = new Node;
        (*h1)->next = tmp;
        tmp->data = 2;
        *h2 = tmp;
        tmp->next = *h1;
    }
    bool isCircle(Node *h,Node **circleNode,Node **lastNode)
    {
        Node *ps = h,*pf = h;
        while(1)
        {
            if(pf && pf->next)
            {
                pf=pf->next->next;
            }
            else
            {
                ps = h;
                while(ps->next!=NULL)
                    ps = ps->next;
                *lastNode = ps;
                return false;
            }
    
            ps=ps->next;
    
            if(ps==pf)
            {
                break;
            }
        }
    
        //没有return false则证明存在环
        //分别从相遇点和第一个节点出发,都是步长为1的指针,当相遇位置即为环首的位置。
        //具体证明见图
        Node *p=h;
        while(p!=ps)
        {
            p=p->next;
            ps=ps->next;
        }
        *circleNode = ps;
        return true;
    }
    bool detect(Node *head1, Node *head2)
    {
        if(head1==NULL || head2==NULL)
            return false;
    
        Node *circleNode1;//链表1的入环点
        Node *circleNode2;//链表2的入环点
        Node *lastNode1;//链表1的最后一个结点(无环)
        Node *lastNode2;//链表2的最后一个结点(无环)
    
        bool isCircle1 = isCircle(head1,&circleNode1,&lastNode1);
        bool isCircle2 = isCircle(head2,&circleNode2,&lastNode2);
    
        //一个有环,一个无环
        if(isCircle1 != isCircle2)
            return false ;
    
        //两个都无环,判断最后一个节点是否相等
        else if (!isCircle1 && !isCircle2)
        {
            return lastNode1 == lastNode2;
        }
    
        //两个都有环,判断环里的节点是否能到达另一个链表环里的节点
        else
        {
            Node *temp = circleNode1->next; 
            while(temp != circleNode1)
            {
                if(temp == circleNode2)
                    return true ;
                temp = temp->next;
            }
            return false ;
        }
        return false ;
    }
    View Code
  • 相关阅读:
    python的函数
    Python的条件语句和循环语句
    Python的输入与输出
    Python变量和类型
    Python的运算符
    Python的注释
    pycharm基本使用
    推特史上最大规模黑客入侵案:17岁问题少年的隐秘人生
    进程和线程的区别及线程的介绍
    python接口自动化42
  • 原文地址:https://www.cnblogs.com/tractorman/p/4054473.html
Copyright © 2011-2022 走看看