还是链表算法


题目描述:给出两个无环单链表
A: a1 → a2

             ↘
               c1 → c2 → c3 → null
             ↗

B: b1 → b2 → b3
判断 A 和 B 是否相交。
除了转化为环的问题,还可以利用“如果两个链表相交于某一节点,那么之后的节点都是共有的”这个特点,如果两个链表相交,那么最后一个节点一定是共有的。所以可以得出另外一种解法,先遍历 A 链表,记住尾节点,然后遍历 B 链表,比较两个链表的尾节点,如果相同则相交,不同则不相交。时间复杂度为 O(Length(A) + Length(B)),空间复杂度为 O(1),思路比解法 2 更简单。想法还是奇妙的。算法写起来不难,难的是想到这个。

 function hasSharedNode(head1, head2){
     if(head1 == null||head2 == null) return false;
     var lastNode1 = head1;
     while(lastNode1.next != null){
       lastNode1 = lastNode1.next;
     }
     var lastNode2 = head2;
     while(lastNode2.next != null){
       lastNode2 = lastNode2.next;
     }
     if(lastNode1 == lastNode2){
     return true;
     }
     else {
     return false;
     }
   }

两个链表相交扩展:判断两个有环单链表是否相交

题目描述:上面的问题是针对无环链表的,如果是链表有环呢?

分析:如果两个有环单链表相交,那么它们一定共有一个环。因此可以先用之前快慢指针的方式找到两个链表中位于环内的两个节点,如果相交的话,两个节点在一个环内,那么移动其中一个节点,在一次循环内肯定可以与另外一个节点相遇。
有环单链表到底是咋样的,就是我们前面说的小b型的结构吧。尾节点的next指向前面的某个节点。如果交点不是在环上,那么肯定是共享一段直线加上一个环。
如果交点是在环上,那么就是共享环,直线阶段是各自独立的。所以结果就是共有一个环。需要用到上次找环入口的那个function。为啥不能用无环链表的算法呢?因为没法判断尾节点。其实也算是用到了,其实环入口就算是尾节点吧。


   function findLoopPort(head){
    if(head==null||head.next==null) return null;
    var fastNode = head;
    var normalNode = head;
    var hasCircle = false;
    while(fastNode != null&&fastNode.next != null){
        fastNode = fastNode.next.next;
        normalNode = normalNode.next;
        if(normalNode == fastNode) {
            hasCircle = true;
            break;
        }
    }
    if(!hasCircle) return null;//原本想return false,后来发现还是null好。
    var fastNode = head;
    while(fastNode != normalNode){
        fastNode = fastNode.next;
        normalNode = normalNode.next;
    }
    return fastNode;
}

function hasSharedNodeWithLoop(head1, head2){
  var loopPort1 = findLoopPort(head1); //head1 head2的null之类的已经在findLoopPort里面判断了。
  var loopPort2 = findLoopPort(head2);
  if(loopPort1 == null || loopPort2 == null){ //无环,则不满足条件,即使无环单链表相交,也返回false
    return false;
  }
  var startNode = loopPort1;
  while(loopPort1.next != startNode){ //保证只在环内转一圈
    if(loopPort1 == loopPort2)
     return true;
     loopPort1 = loopPort1.next;
  }
  return false; //转完一圈没发现共同的节点,则没相交点。
}

两个链表相交扩展:求两个无环单链表的第一个相交点

LeetCode 160. Intersection of Two Linked Lists
题目描述:找到两个无环单链表第一个相交点,如果不相交返回空,要求在线性时间复杂度和常量空间复杂度内完成。我的想法是如果求得最后一个尾节点,然后让尾节点的next指向其中的一个的头,那么肯定就构成了一个有环单链表。然后求得环的入口就是第一个相交点。主要是感觉一步一步的,好像都在复用前面的东西。所以就想到了这个。


好多知识不知道
21 声望0 粉丝

想法,每个人都有,每时每刻。想法并不会一直留在脑中,时间会遗忘一切,有必要整理一些东西,记住那时的你。思维是最美的东西,让不同时间的你,用思维对话。(起高了)