单向链表的结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Link { public int data; public Link next; public Link (int data) { this .data=data; } public String toString () { return String.format("data:%s" ,this .data); } }
单向链表是否有环 这题的思路很简单,先创建两个指针都指向链表的头部,一个fast指针每次走两步,另一个slow指针每次都走一步,如果fast指针能走到null的地方就说明该单链表没有环,否则fast和slow节点一定会走到同一个节点,表示有环
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 /** * 判断是否有环 * @param head * @return */ public static boolean isCycle (Link head) { boolean flag=false ; if (head!=null ) { Link fast=head,slow=head; while (fast!=null && fast.next!=null ) { slow=slow.next; fast=fast.next.next; if (fast==slow) { flag=true ; break ; } } } return flag; }
判断两个单向链表是否相交 这里可以想一下,单向链表的相交是什么情况? 那肯定是一个Y字形的,因为两个链表都是单向的嘛^_^,所以有两种解法
利用上面的环,先遍历其中一个链表,另其首尾相连,(其实如果相交就会构成一个含有环的单链表),此时再从另一个链表的头部出发找是否有环就可以了
将两个链表都遍历到尾结果,如果这两个尾节点是同一个节点,说明就是相交
其实还可以使用hash的方法,也就是遍历两个链表进行hash,同一个节点的hash值肯定是一样的,然后就是两个集合的包含元素查找即可
判断两个相交的链表的交点1 其实这里根据上一问可知,如果有交点,那个交点就是环的入口点,所以先根据环的方法找入口点,然后将fast指针指向链表的头部,但是这个fast节点之后都是走一步,和slow同时走,它们相等的地方就是环的交点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 /** * 两个链表是否相交 就是Y形状 * @param head * @return //如果相交 返回交点 */ public static Link isY (Link head1,Link head2) { Link y=null ; if (head1!=null && head2!=null ) { Link h=head1; while (h.next!=null ) h=h.next; h.next=head1; boolean flag=false ; if (head2!=null ) { Link fast=head2,slow=head2; while (fast!=null && fast.next!=null ) { slow=slow.next; fast=fast.next.next; if (fast==slow) { flag=true ; break ; } } if (flag) { fast=head2; while (slow!=fast) { slow=slow.next; fast=fast.next; } y=fast; } } h.next=null ; } return y; }
ps.如果需要看交点具体的推导看http://www.cnblogs.com/BeyondAnyTime/archive/2012/07/06/2580026.html
判断两个相交的链表的交点2 求出两个单链表的尾节点,在这个过程中可以很容易得到两个链表的长度,len1,len2,然后先让长的链表走abs(len1-len2),然后让两个链表齐头并进就可以找到交点,复杂度是O(n+m)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 /** * 两个链表是否相交 就是Y形状 * 首先首先将两个环各自走到尾部,记录tail1和len1,以及tail2和len2 * 如果tail1=tail2 则相交 * 然后先让长的链表走abs(len1-len2),然后让两个链表齐头并进就可以找到交点,复杂度是O(n+m) * @param head1 * @param head2 * @return */ public static Link isY2 (Link head1,Link head2) { Link y=null ; if (head1!=null && head2!=null ){ Link tail1=head1,tail2=head2; int len1=1 ,len2=1 ; while (tail1.next!=null ) { len1++; tail1=tail1.next; } while (tail2.next!=null ) { len2++; tail2=tail2.next; } if (tail1==tail2) { Link longLink=head1,shortLink=head2; if (len1<len2) { longLink=head2; shortLink=head1; } int diff=Math.abs(len1-len2); while (diff>0 ) { longLink=longLink.next; diff--; } while (longLink!=shortLink) { longLink=longLink.next; shortLink=shortLink.next; } y=longLink; } } return y; }
演示结果代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public static void main (String[] args) { Link head1=new Link(1 ); Link link1=new Link(2 ); head1.next=link1; Link link2=new Link(3 ); link1.next=link2; Link link3=new Link(4 ); link2.next=link3; Link link4=new Link(5 ); link3.next=link4; Link link5=new Link(6 ); link4.next=link5; System.out.println(isCycle(head1)); link5.next=link2; System.out.println(isCycle(head1)); link5.next=null ; Link head2=new Link(7 ); Link link6=new Link(8 ); head2.next=link6; Link link7=new Link(9 ); link6.next=link7; System.out.println(isY(head1,head2)); link7.next=link2; System.out.println(isY(head1,head2)); }
具体结果
false
true
null
data: 3
本作品采用[知识共享署名-非商业性使用-相同方式共享 2.5] 中国大陆许可协议进行许可,我的博客欢迎复制共享,但在同时,希望保留我的署名权kubiCode ,并且,不得用于商业用途。如您有任何疑问或者授权方面的协商,请给我留言 。