程序员面试经典--链表环路检测与入口结点返回

来源:互联网 发布:查看一个ip绑定的域名 编辑:程序博客网 时间:2024/05/23 02:02

2.6问题:

给定一个有环链表,实现一个算法返回环路的开头结点。

思考:

第一:监测链表是否存在环路。有一种简单的方法叫做fastrunner/slowrunner法。fastruner一次移动两步,slowrunner一次移动一步。如果存在环路,最终必然会碰到一起。

第二:什么时候碰到一起?

    1、slowrunner处于环路中的0步位置;

    2、fastrunner处于环路中的k步位置;

    3、slowrunner落后于fastrunner,相距k步;

    4、fastrunner落后于slowrunner,相距LOOP_SIZE-k步;

那么,若fastrunner 落后于slowrunner,相距LOOP_SIZE-k步,那么两者将会在LOOP_SIZE-k步之后相遇。此时,两者与环路起始处相距k步,我们将这个位置称为collisionSopt。

第三:如何找到环路起始处?现在我们知道,collisionSpot与环路起始处相距k个结点。即:collisionSpot和linkedListHead与环路起始处均相距k个结点。现在,若用一个指针指向collisionspot,用另一个指针指向linkedlisthead,两者与loopstart相距k个结点。以同样的速度移动,这两个指针会再次碰在一起------这次是在k步之后,此时两个指针都指向loopstart,然后只需返回该结点即可。


算法思路:

1、创建两个指针:fastpointer和slowpointer。

2、slowpointer每走一步,fastpointer就走两步。

3、两者碰在一起时,将slowpointer指向linkedlisthead,fastpointer保持不变。

4、以相同的速度移动slowpointer和fastpointer,一次一步,然后返回新的碰撞处。

import java.util.*;//节点类class Node {protected Node next; //指针域protected int data;//数据域 public Node( int data) {this.data = data;} //显示此节点public void display() {System. out.print( data + " ");}}//单链表class LinkList {public Node first; // 定义一个头结点private int pos = 0;// 节点的位置public LinkList() {this.first = null;//this代表当前类}// 插入一个头节点public void addFirstNode( int data) {Node node = new Node(data);node. next = first;first = node;}// 显示出所有的节点信息public void displayAllNodes() {Node current = first;while (current != null) {current.display();current = current. next;}System. out.println();}}class findBeginning{public static void main(String args[]){LinkList linkList = new LinkList();linkList.addFirstNode(11);//56Node tail=linkList.first;linkList.addFirstNode(10);//456linkList.addFirstNode(9);//3456linkList.addFirstNode(8);//23456linkList.addFirstNode(7);//123456linkList.addFirstNode(6);//6linkList.addFirstNode(5);//56linkList.addFirstNode(4);//456Node aa=linkList.first;linkList.addFirstNode(3);//3456linkList.addFirstNode(2);//23456linkList.addFirstNode(1);//123456System.out.println("原链表为:");linkList.displayAllNodes();//构造环路。tail.next = aa;//将第11个结点指向第4个结点形成环路。System.out.println("环路入口结点数据为:"+findBeginning(linkList.first).data);}public static Node findBeginning(Node head){Node slow=head;Node fast=head;while(fast!=null&&fast.next!=null){slow=slow.next;fast=fast.next.next;if(slow == fast){break;}}if(fast==null||fast.next==null){return null;}slow=head;while(slow!=fast){slow=slow.next;fast=fast.next;}return fast;}}

0 0