链表环的判断,是否相交

来源:互联网 发布:站长工具域名查询 编辑:程序博客网 时间:2024/06/06 03:19

1.单链表是否有环

题目:

判断一个单链表是否有环?有环的话返回进入环的第一个节点的值,无环的话返回-1。如果链表的长度为N,请做到时间复杂度O(N),额外空间复杂度O(1)。

 

思路:

快慢两个指针,快指针一次走2步,慢指针一次走1步。如果两指针相遇则有环。有环后慢指针继续每次一步,快指针从头结点开始每次一步,再次相遇节点为环的入口节点。

 

public class ChkLoop {    public int chkLoop(ListNode head, int adjust) {        // write code here        if(head==null||head.next==null) return -1;        ListNode fast=head;        ListNode slow=head;        boolean ring=false;                 while(fast!=null&&fast.next!=null){            slow=slow.next;            fast=fast.next.next;//这两句一定要在if之前,因为初始时都指向head。            if(slow==fast){//快慢指针相遇,有环                ring=true;                break;            }                                  }        fast=head;//fast从头开始,每次一步        while(ring){            if(fast==slow){//再次相遇,环的入口                return fast.val;            }            fast=fast.next;            slow=slow.next;        }        return -1;    }}



2.无环链表是否相交:

题目:

两个无环单链表,若两个链表的长度分别为m和n,请设计一个时间复杂度为O(n + m),额外空间复杂度为O(1)的算法,判断这两个链表是否相交。

 

思路:

(1)两个链表长度假设m1=100,m2=70,各自指针从头p1,p2。先让p1走m1-m2=30步,然后p1,p2同时步长为1向前走,当遇到两个指针指向同一节点时,表名相交,如果有一个为null时不想交。

(2)如果没有给定两个链表长度,那么先遍历到第一个链表的尾节点,将其next指向第二个链表的头结点(尾节点.next原本为null)。这样的话判断两个链表是否相交=判断一个链表是否有环。相交起点=环的入口。

(3)如果两个链表相交,那么他们的尾节点一定是相交的,整体类似Y字型。所以分别遍历到尾节点,看尾节点是否相同即可。

(4)先分别遍历两个链表,记录他们长度m1,m2,然后按照步骤1开始。

 

public class CheckIntersect {    public boolean chkIntersect(ListNode headA, ListNode headB) {        // write code here        if(headA==null||headB==null) return false;        ListNode p1=headA;        ListNode p2=headB;        while(p1.next!=null){//两链表尾节点是否相同            p1=p1.next;        }        while(p2.next!=null){            p2=p2.next;        }        if(p1==p2) return true;        return false;    }}

public class CheckIntersect {    public boolean chkIntersect(ListNode headA, ListNode headB) {        // write code here        if(headA==null||headB==null) return false;        int len1=0;        int len2=0;        ListNode p1=headA;        ListNode p2=headB;        while(p1!=null){            len1++;            p1=p1.next;        }        while(p2!=null){            len2++;            p2=p2.next;        }                                    int n=0;        p1=headA;p2=headB;        ListNode meet=null;                 if(len1>=len2){            n=len1-len2;            while(n>0){                p1=p1.next;                n--;            }            p1=p1.next;            while(p1!=null){                if(p1==p2) {                    meet=p1;                    return true;                }                p1=p1.next;                p2=p2.next;            }        }else{              n=len2-len1;            while(n>0){                p2=p2.next;                n--;            }            p2=p2.next;            while(p1!=null){                if(p1==p2) {                    meet=p1;                    return true;                }                p1=p1.next;                p2=p2.next;            }        }        return false;    }}



3.两个有环单链表是否相交

判断两个有环单链表是否相交?相交的话返回第一个相交的节点,不想交返回null。如果两个链表长度分别为N和M,请做到时间复杂度O(N+M),额外空间复杂度O(1)。

给定两个链表的头结点head1head2

 

思路:

(1)首先,找到两个链表各自的入环节点node1,node2.如果node1=node2,那么必然相交.

即:如果在刚入环的时候已经相交,其实第一个相交节点应该在环前面。如图,此时就=两个无环单链表的第一个相交节点,唯一区别是尾节点是null。



(2)两个链表的入环节点不同node1!=node2:node2不动,让node1开始往下走,回到原node1之前没有遇到node2,说明两个链表不想交。反之相交,相交的第一个节点可以是node1也可以是node2.如图,

 

4.判断两个链表是否相交

(1)先判断两个是否有环,找到入环节点。(一个有环,一个无环是不能相交的)

(2)如果是两个无环链表就用方法2来判断是否相交

(3)如果两个有环链表就用方法3来判断是否相交。