链表的相交、环问题

来源:互联网 发布:lamp linux版本 编辑:程序博客网 时间:2024/05/18 15:28

链表的基础问题:给定一个链表,返回倒数第K个数。

  这里链表的定义如下:
package linkedlist;public class ListNode {int data;ListNode next;public static ListNode buildList(int[] array){ListNode head = new ListNode();head.data = array[0];ListNode temp = head;for(int i = 1 ; i < array.length ; i++){ListNode t = new ListNode();t.data = array[i];temp.next = t;temp = t;}return head;}}

//这里使用buildList(int[] array)初始化链表

//下面的方法默认使用aList与bList两个链表。


解决:

方法很简单,相信很多人都看过,定义两个指针a,b(Java中是对象的引用,这里使用指针代替),将b向后移动K-1个单位,然后a与b同时向后移动,直至b.next为null。得到倒数的K个数。
public int lastK(int k) {ListNode pre = aList;ListNode last = aList;while(pre != null && k > 1){pre = pre.next;k-- ;}if(k > 1){System.out.println("error!!");}while(pre.next != null){pre = pre.next;last = last.next;}return last.data;}

下面来看链表相交的问题

  假定两个链表没有环,判断链表是否相交。

              对于上面的的问题,最简单的方法也就是遍历,设有两个链表A和B,首先遍历a链表,每遍历A链表的一个结点,遍历一次B链表。时间复杂度为O(A.length * B.length)。
              毫无疑问,上面的方法最简单,同时也是最耗时的。我们可以在遍历A链表的过程中,将结点保存在Hash表中,再遍历B链表,每访问一个结点,便在Hash表里查询有没有此节点。因为访问Hash表的时间可以认为是O(1),因此时间复杂度为              O(A.length + B.length),空间复杂度为O(A.length)。
               考虑两个链表如果相交,则必有共同的结尾,可以参考下图。有这个性质,只需判断两个链表是否有共同的结尾即可。

(图片来自http://blog.csdn.net/v_july_v/article/details/6447013)
           
       
public boolean isIntersect(){ListNode aPoint = aList;ListNode bPoint = bList;//aList的末尾while(aPoint.next != null){aPoint = aPoint.next;}//bList的末尾while(bPoint.next != null){bPoint = bPoint.next;}//是否相等return (aPoint == bPoint);}
            

链表的环问题:

            判断一个链表是否存在环,可以采用Hash表的方法,将链表向前遍历,将访问的的结点存放在Hash表中,如果指针达到null,则没有环。如果访问的结点在Hash表中,则链表有环。
            上述方法的时间复杂度为O(List.length),需要一个链表长度的空间。
    那么有没有线性时间同时空间复杂度为O(1)的算法呢。个人认为还得从问题的性质入手。仔细观察有环链表的性质,当链表进入环后,会一直在环中转,
           
          访问顺序为1 --->  2 --->  3 ---> 4 ----> 5  ---> 3 ---> 4 ----> 5 ---> 4 ----> 5........
          是不是很像运动会的跑步,在跑步中,如果一个人跑的慢,另一个人跑的快一点,最终会快的人会从后面超过慢的人。
          因此我们可以使用两个指针a和b,a每次前进一个,b每次前进两个结点,最终a与b都会进入环,且b先进入,a后进入,由于b的速度快,所以最终会赶上b,从而a == b。若链表中没有环,则不会赶上。


0 0