剑指offer——链表中环的入口结点(好题,思路)

来源:互联网 发布:wifi搞怪软件下载 编辑:程序博客网 时间:2024/06/05 15:55

题目描述
一个链表中包含环,请找出该链表的环的入口结点。

思路:
有环的链表的特点是,永远有next值,所以无法辨别在哪一刻已经遍历完链表。

假设node的类可以自定义,那么再增加一个boolean变量表示是否被访问就能简单解决问题。或者用HashMap将当前节点设为key,下一节点设为value,关联起来。但也要自定义Hash的方法。在Object类中的定义为:public native int hashCode(); 是一个本地方法,返回的对象的地址值。
或者用HashSet

如果一个链表的所有元素的值都相同,而环是其中的一小部分,则必须从对象本身的特性(如内存中地址)来区分他们的不同,从而找到入口。


利用HashSet

import java.util.*;public class Solution {    public ListNode EntryNodeOfLoop(ListNode pHead)    {        if(pHead==null)            return null;        HashSet<ListNode> set = new HashSet<>();        while(pHead!=null){        if(set.contains(pHead)==false){            set.add(pHead);            pHead = pHead.next;        }            else                return pHead;        }        return null;    }}

剑指offer的思路:
1. 得到环中节点数
2. 设置一快一满两个指针,之间的距离差为环的大小,当两者相遇时即得到环的入口节点

得到环中节点数的方法:
用一快一慢两个指针。如果两个指针相遇,表明链表中存在环。两个指针相遇的结点一定是在环中。可以从这个结点出发, 一边继续向前移动一边计数, 当再次回到这个结点时, 就可以得到环中结点数了。

public class Solution {    public static ListNode EntryNodeOfLoop(ListNode pHead)    {        if(pHead==null||pHead.next==null)            return null;        ListNode pFirst = pHead.next;        ListNode pSecond = pHead.next.next;        while(pFirst!=null&&pSecond!=null&&pFirst!=pSecond){            pFirst = pFirst.next;            pSecond = pSecond.next.next; // 保证行进速度一块一慢!        }        if(pFirst==null||pSecond==null)            return null;        ListNode pTemp = pFirst;        int n = 1;        while(pFirst.next!=pTemp){            pFirst = pFirst.next;            n++;        }        pFirst = pHead;        pSecond = pHead;        while(n>0){            pSecond = pSecond.next;            n--;        }        while(pSecond!=pFirst){            pFirst = pFirst.next;            pSecond = pSecond.next; // 行进速度相同,初始节点不同        }        return pFirst;    }
原创粉丝点击