• 3.6 判断两个链表是否相交


    判断两个链表是否相交,若相交则求其交点(指第一个相交的点)。

    思路1,利用计数法: 遍历链表1,将其节点的内存地址存入map或者hashmap内。然后遍历链表2,并查询map或者hashmap,判断链表2节点是否在里面。若存在,则两者相交,且交于此节点。此方法时间复杂度是O(Length(List1)+Length(List2))且需要O(Length(List1))的空间存储hashmap。如下面代码的isCross_method1

     

    思路2, 计数法优化: 我们知道,若两链表相交,则交点之后的链表均为两链表所共有。因此,若两者相交,则两者最后的节点一定相同。 所以只需要比较两链表最后的节点即可。此方法虽然时间复杂度也为O(Length(List1)+Length(List2)),但只需要O(1)个空间存储最后一个节点就可以。至于求交点,则需要直到两链表的长度(假设Length1>Length2),链表1先走Length1-Length2步,再同时开始走,直到节点相同的点,就是交点。然后如下面代码的isCross_method2

     

    思路3, 人为构造环:将链表1的尾节点指向链表2的头节点。问题变为,判断此新链表是否有环,并求环入口点。相关问题可参照这里解决。

    需要注意的是判断结束后要将两链表分开。

    全部代码如下:

      1 #include "stdafx.h"
      2 #include <iostream>
      3 #include <hash_map>
      4 
      5 using namespace std;
      6 
      7 const int LONG_LENGTH = 13;
      8 const int SHORT_LENGTH = 4;
      9 
     10 typedef struct node{
     11     int value;
     12     struct node *next;
     13 }node;
     14 
     15 //构造两相交链表,相较于第crossNum个节点。另外为了方便测试, isCross控制两链表是否相交
     16 bool createCrossLink(node *list1,node *list2,int crossNum,bool isCross){
     17     
     18     if(crossNum<0 || crossNum>=LONG_LENGTH) return false;
     19 
     20     node *temp,*last,*longList,*shortList;
     21     longList = list1;
     22     shortList = list2;
     23     //last = (node *)malloc(sizeof(node)); last可以不需要分配内存
     24 
     25     for(int i=LONG_LENGTH-1;i>=0;i--){
     26         node *lp = (node *)malloc(sizeof(node));
     27         lp->value = i;
     28         lp->next = longList->next;
     29         longList->next = lp;
     30         if(i==crossNum){
     31             temp = lp;            //temp是交点
     32         }
     33     }
     34 
     35     for(int i=SHORT_LENGTH-1;i>=1;i--){
     36         node *sp = (node *)malloc(sizeof(node));
     37         sp->value = i*100;
     38         sp->next = shortList->next;
     39         shortList->next = sp;
     40         if(i==SHORT_LENGTH-1){
     41             last = sp;           //last是链表2最后一个节点
     42         }
     43     }
     44 
     45     if(isCross) last->next = temp;
     46     return true;
     47 }
     48 
     49 //遍历链表
     50 void traverse(node *p){
     51     node * ptr = p;
     52     while(ptr!=NULL){
     53         cout<<ptr->value;
     54         if(ptr->next!=NULL) cout<<" -> ";
     55         ptr = ptr->next;
     56     }
     57     cout<<endl;
     58 }
     59 
     60 //思路1,利用hash_map
     61 bool isCross_method1(node *l1,node *l2){
     62 
     63     if(l1==NULL || l2==NULL) return false;
     64 
     65     node *firstPtr,*secondPtr;
     66     firstPtr = l1;
     67     secondPtr = l2;
     68 
     69     hash_map<node *,int> ptrMap;
     70     hash_map<node *,int>::iterator it;
     71 
     72     while(firstPtr!=NULL){
     73         ptrMap.insert(pair<node *,int>(firstPtr,firstPtr->value));
     74         firstPtr = firstPtr->next;
     75     }
     76     
     77     for(it=ptrMap.begin();it!=ptrMap.end();it++){
     78         cout<<(*it).first<<" => "<<(*it).second<<endl;
     79     }
     80 
     81     while(secondPtr!=NULL){
     82         if(ptrMap.find(secondPtr)!=ptrMap.end()){
     83             cout<<"Crossing at: "<<secondPtr<<endl;
     84             return true;
     85         }
     86         secondPtr = secondPtr->next;
     87     }
     88 
     89     return false;
     90 }
     91 
     92 //思路2
     93 bool isCross_method2(node *l1,node *l2){
     94     
     95     if(l1==NULL || l2==NULL) return false;
     96 
     97     node *firstPtr,*secondPtr,*first,*second;
     98     firstPtr = l1;
     99     secondPtr = l2;
    100     int firLen = 0;
    101     int secLen = 0;
    102 
    103     while(firstPtr!=NULL){
    104         if(firstPtr->next==NULL) first=firstPtr;
    105         firstPtr=firstPtr->next;
    106         firLen++;
    107     }
    108     while(secondPtr!=NULL){
    109         if(secondPtr->next==NULL) second=secondPtr;
    110         secondPtr=secondPtr->next;
    111         secLen++;
    112     }
    113 
    114     if(first==second){  //判断尾节点是否相等
    115         firstPtr = l1;  //要将指针重新指向两节点的头节点,再开始找交点!
    116         secondPtr = l2;
    117         if(firLen>secLen){
    118             for(int i=0;i<firLen-secLen;i++){
    119                 firstPtr = firstPtr->next;
    120             }
    121         }else{
    122             for(int i=0;i<secLen-firLen;i++){
    123                 secondPtr = secondPtr->next;
    124             }
    125         }
    126 
    127         while(firstPtr!=secondPtr){
    128             firstPtr=firstPtr->next;
    129             secondPtr = secondPtr->next;
    130         }
    131 
    132         cout<<"Crossing at: "<<firstPtr<<":"<<firstPtr->value<<" , "<<secondPtr<<":"<<secondPtr->value<<endl;
    133         return true;
    134     }else 
    135         return false;
    136 }
    137 
    138 int _tmain(int argc, _TCHAR* argv[])
    139 {
    140     node *longHead = (node *)malloc(sizeof(node));
    141     node *shortHead = (node *)malloc(sizeof(node));
    142     longHead->next = NULL;
    143     shortHead->next = NULL;
    144 
    145     if(createCrossLink(longHead,shortHead,6,true)){
    146         traverse(longHead->next);
    147         traverse(shortHead->next);
    148 
    149         cout<<isCross_method1(longHead->next,shortHead->next)<<endl;;
    150         cout<<endl;
    151         cout<<isCross_method2(longHead->next,shortHead->next)<<endl;;
    152     }
    153 
    154     return 0;
    155 }

    以上均假设两链表无环,如不知两者是否有环,则需要分步骤解决:

    1. 若两者均无环,按上述思路解决

    2. 若一个有环,一个无环,则两者不相交(因为不可能无环链表与有环链表相交,这样无环链表也会变有环)

    3. 若两者皆有环,则可求出链表1的入口节点是否在链表2的环中,若在则相交。相交时环必为两者共有。

    环相关问题,请参考这里

    参考:

    http://blog.csdn.net/liuxialong/article/details/6556096

  • 相关阅读:
    Keil(MDK) 5 软件安装教程
    JPA 的specification动态查询
    idea 建立JPA项目(二)
    HBase单节点的安装与配置
    【codevs3012+codevs3037】线段覆盖4+线段覆盖5(DP)
    MySQL下载和安装教程
    二、单线程的 JavaScript
    #JS 基础之异步(一)
    JS 基础之: 继承的 六 种实现方式
    源码浅析-Vue3中的13个全局Api
  • 原文地址:https://www.cnblogs.com/techyc/p/2694810.html
Copyright © 2020-2023  润新知