• 两个单链表相交的一系列问题


    【说明】:

      本文是左程云老师所著的《程序员面试代码指南》第二章中“两个单链表相交的一系列问题”这一题目的C++复现。

      本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。

      感谢左程云老师的支持。

    【题目】:

      在本题中,单链表可能有环也可能无环。给定两个单链表的头节点 head1 和 head2,这两个单链表可能相交也可能不相交。请实现一个函数,如果两个链表相交,请返回相交的第一个节点;如果不相交,返回 NULL。

     【思路】:

      将本问题拆分成3个子问题:

        1、判断一个链表是否有环

        2、判断两个无环链表相交的问题

        3、判断两个有环链表相交的问题

        4、一个有环一个无环则肯定不相交  

    【编译环境】:

      CentOS6.7(x86_64)

      gcc 4.4.7

     【实现】:

      实现及测试代码:

      1 /*
      2  *文件名:list_intersect.cpp
      3  *作者:
      4  *摘要:链表相交的一系列问题
      5  */
      6 
      7 #include <iostream>
      8 #include<stdlib.h>
      9 
     10 using namespace std;
     11 
     12 class Node
     13 {
     14 public:
     15     Node(int data)
     16     {
     17         value = data;
     18         next = NULL;
     19     }
     20 public:
     21     int value;
     22     Node *next;
     23 };
     24 
     25 //找到入环节点
     26 Node* getLoopNode(Node *head)
     27 {
     28     if(NULL == head || NULL == head->next || NULL == head->next->next)
     29         return NULL;
     30     Node *n1 = head->next;
     31     Node *n2 = head->next->next;
     32     while(n1 != n2)
     33     {
     34         if(NULL == n2->next || NULL == n2->next->next)
     35             return NULL;
     36         n2 = n2->next->next;
     37         n1 = n1->next;
     38     }
     39     n2 = head;
     40     while(n1 != n2)
     41     {
     42         n1 = n1->next;
     43         n2 = n2->next;
     44     }
     45     return n1;
     46 }
     47 
     48 //不带环的链表的相交节点
     49 Node* noLoop(Node *head1,Node *head2)
     50 {
     51     if(NULL == head1 || NULL == head2)
     52         return NULL;
     53     Node *cur1 = head1;
     54     Node *cur2 = head2;
     55     int n = 0;
     56     
     57     while(NULL != cur1->next)
     58     {
     59         n++;
     60         cur1 = cur1->next;
     61     }
     62     while(NULL != cur2->next)
     63     {
     64         n--;
     65         cur2 = cur2->next;
     66     }
     67 
     68     if(cur1 != cur2)    //若最后一个节点不想等,则俩链表不相交
     69         return NULL;
     70     
     71     cur1 = n > 0 ? head1 : head2;
     72     cur2 = cur1 == head1 ? head2 : head1;
     73     n = abs(n);
     74     while(0 != n)  //以较短的那个链表为准
     75     {
     76         n--;
     77         cur1 = cur1->next;
     78     }
     79     while(cur1 != cur2)
     80     {
     81         cur1 = cur1->next;
     82         cur2 = cur2->next;
     83     }
     84     return cur1;
     85 }
     86 
     87 //带环链表的相交节点的判断
     88 Node* bothLoop(Node *head1,Node *loop1,Node *head2,Node *loop2)
     89 {
     90     Node *cur1(NULL),*cur2(NULL);
     91     
     92     if(loop1 == loop2)    //与不带环的相交节点的判断一样的
     93     {
     94         cur1 = head1;
     95         cur2 = head2;
     96         int n = 0;
     97         while(cur1 != loop1)
     98         {
     99             n++;
    100             cur1 = cur1->next;
    101         }
    102 
    103         while(cur2 != loop2)
    104         {
    105             n--;
    106             cur2 = cur2->next;
    107         }
    108         cur1 = n > 0 ? head1 : head2;
    109         cur2 = cur1 == head1 ? head2 : head1;
    110         n = abs(n);
    111         while(0 != n)
    112         {
    113             n--;
    114             cur1 = cur1->next;
    115         }
    116         while(cur1 != cur2)
    117         {
    118             cur1 = cur1->next;
    119             cur2 = cur2->next;
    120         }
    121         return cur1;
    122     }
    123     else
    124     {
    125         cur1 = loop1->next;
    126         while(cur1 != loop1)
    127         {
    128             if(cur1 == loop2)
    129                 return loop2;
    130             cur1 = cur1->next;
    131         }
    132         return NULL;
    133     }
    134 }
    135 
    136 Node* getIntersectNode(Node *head1,Node *head2)
    137 {
    138     if(NULL == head1 || NULL == head2)
    139         return NULL;
    140     Node *loop1 = getLoopNode(head1);
    141     Node *loop2 = getLoopNode(head2);
    142     if(NULL == loop1 && NULL == loop2)
    143         return noLoop(head1,head2);
    144     if(NULL != loop1 && NULL != loop2)
    145         return bothLoop(head1,loop1,head2,loop2);
    146     return NULL;
    147 }
    148 
    149 
    150 int main()
    151 {
    152     Node *head1 = NULL;
    153     Node *head2 = NULL;
    154     Node *ptr1 = NULL;
    155     Node *ptr2 = NULL;
    156     Node *head3 = NULL;
    157     Node *ptr3 = NULL;
    158     for(int i =0;i<4;i++)//构造链表
    159     {
    160         if(NULL == head1 || NULL == head2)
    161         {    
    162             head1 = new Node(i);
    163             head1->next = NULL;
    164             ptr1 = head1;
    165             head2 = new Node(i);
    166             head2->next = NULL;
    167             ptr2 = head2;
    168             head3 = new Node(10-i);
    169             head3->next = NULL;
    170             ptr3 = head3;
    171             continue;
    172         }
    173         ptr1->next = new Node(i);
    174         ptr1 = ptr1->next;
    175         ptr1->next = NULL;
    176         ptr2->next = new Node(i);
    177         ptr2 = ptr2->next;
    178         ptr2->next = NULL;
    179         ptr3->next = new Node(10-i);
    180         ptr3 = ptr3->next;
    181         ptr3->next = NULL;
    182     }
    183     //第一:无环不相交
    184     if(NULL == getIntersectNode(head1,head2))
    185         cout << "Two lists are not intersecting!" << endl;
    186     //第二:有环不相交
    187     ptr1->next = head1->next;
    188     ptr2->next = head2->next;
    189     if(NULL == getIntersectNode(head1,head2))
    190         cout << "Two lists are not intersecting!" << endl;    
    191     //第三:无环相交
    192     ptr1->next = head3;
    193     ptr2->next = head3;
    194     if(NULL != getIntersectNode(head1,head2))
    195         cout << "Two lists are intersecting!" << getIntersectNode(head1,head2)->value << endl;
    196     //第四有环相交
    197     ptr3->next = head3;
    198     if(NULL != getIntersectNode(head1,head2))
    199         cout << "Two lists are intersecting!" << getIntersectNode(head1,head2)->value << endl;
    200     return 0;
    201 }
    View Code

    注:

      转载请注明出处;

      转载请注明源思路来自于左程云老师的《程序员代码面试指南》。

  • 相关阅读:
    Hibernate Annotation 生成数据库表(UUId)
    Hibernate用注解生成表
    Java语言 链接Oracle数据库
    Oracle 启动监听命令
    java.lang.IllegalArgumentException异常 数据库别名问题
    java.lang.IllegalArgumentException异常 返回值类型的问题
    java.lang.IllegalArgumentException异常 配置文件的问题
    JUnit 异常处理
    DIV水平垂直布局
    Java 链接SQL Server 数据库
  • 原文地址:https://www.cnblogs.com/PrimeLife/p/5382250.html
Copyright © 2020-2023  润新知