《剑指offer》——链表中环的入口结点

来源:互联网 发布:d3.js tree demo 编辑:程序博客网 时间:2024/06/05 23:45

T:

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

基本做法

不考虑其中潜在的规律,就按照一般的方法,创建一个list,把扫描过的节点都存储在list中,知道下一个节点在list中已经存在,那就说明该节点就是入口节点。

这种方式下的时间复杂度为O(n2)

我的code:

    /*     public class ListNode {        int val;        ListNode next = null;        ListNode(int val) {            this.val = val;        }    }    */    import java.util.ArrayList;    import java.util.List;    /**     * T: 链表中环的入口结点     *     * 题目描述     * 一个链表中包含环,请找出该链表的环的入口结点。     *     * date: 2015.12.13  19:28     * @author SSS     *     */    public class Solution {        /**         * 将所有扫描过的节点都放在list列表中,         * 看是否下一个节点已经在list列表中出现过         * @param pHead         * @return         */        public ListNode EntryNodeOfLoop(ListNode pHead){            ListNode targetNode = new ListNode(3);            if (pHead == null || pHead.next == null) {                return null;            }            List<ListNode> nodesList = new ArrayList<ListNode>();            nodesList.add(pHead);            targetNode = pHead.next;            while (!nodesList.contains(targetNode)) {                nodesList.add(targetNode);                targetNode = targetNode.next;            }            return targetNode;        }    }

规律求解

首先是设置两个指针p1,p2,一个指针p1步长为1,p2步长为2,让两个指针都从头结点往后走,如果存在环的话,两者肯定会再次相遇,因为在两个指针都进入环的时候,一个步长为2,一个步长为1,那就是说两个指针之间的距离每走一步就缩小1个单位,所以两个指针肯定会再次相遇。

在相遇的时候,假设指针p1走了x步,那么p2肯定走了2x步,因为每次p2都比p1多走了一步。

同时,还会发现,这个p2多走的x步,肯定是多走在了换上,也就是说,x是环的长度n的整数倍,即有如下公式:

2x=x+knk=1,2,3,

p2至少围着环转了一圈。

这里写图片描述

也就说,让一个指针指向环上的相遇点,一个指针指向头结点,同时以步长为1往后走,其碰头的那个结点,就是入口结点。

我的code:

    /*     public class ListNode {        int val;        ListNode next = null;        ListNode(int val) {            this.val = val;        }    }    */    /**     * T: 链表中环的入口结点     *     * 题目描述     * 一个链表中包含环,请找出该链表的环的入口结点。     *     * date: 2015.12.13  19:39     * @author SSS     *     */    public class Solution {        /**         * 两个指针,一个指针步长为1,一个步长为2;         * 先计算两个指针相交的位置点;         * 然后让一个指针指向头结点,步长都为1,往后走,其相遇点就是入口点         * 该规律可通过公式推导得出         * @param pHead         * @return         */        public ListNode EntryNodeOfLoop(ListNode pHead){            ListNode targetNode = new ListNode(3);            if (pHead == null || pHead.next == null) {                return null;            }            ListNode preNode = pHead.next;            ListNode postNode = pHead.next.next;            // 找到相遇点            while (preNode != postNode) {                preNode = preNode.next;                postNode = postNode.next.next;            }            // 将其中一个指针指向头结点            postNode = pHead;            // 步长都为1,同时往后走,直到两者相遇            // 相遇点就是入口            while (preNode != postNode) {                preNode = preNode.next;                postNode = postNode.next;            }            targetNode = preNode;            return targetNode;        }    }
0 0
原创粉丝点击