《剑指offer》——链表中环的入口结点
2015-12-13 20:02
459 查看
T:
题目描述
一个链表中包含环,请找出该链表的环的入口结点。
这种方式下的时间复杂度为O(n2)O(n^2)
我的code:
在相遇的时候,假设指针p1p_1走了xx步,那么p2p_2肯定走了2x2x步,因为每次p2p2都比p1p_1多走了一步。
同时,还会发现,这个p2p_2多走的xx步,肯定是多走在了换上,也就是说,xx是环的长度nn的整数倍,即有如下公式:
2x=x+k∗nk=1,2,3,…2x = x + k*n \qquad k = 1,2,3,\dots
p2p_2至少围着环转了一圈。
![](http://img.blog.csdn.net/20151213200056737)
也就说,让一个指针指向环上的相遇点,一个指针指向头结点,同时以步长为1往后走,其碰头的那个结点,就是入口结点。
我的code:
题目描述
一个链表中包含环,请找出该链表的环的入口结点。
基本做法
不考虑其中潜在的规律,就按照一般的方法,创建一个list,把扫描过的节点都存储在list中,知道下一个节点在list中已经存在,那就说明该节点就是入口节点。这种方式下的时间复杂度为O(n2)O(n^2)
我的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,p2p_1, p_2,一个指针p1p_1步长为1,p2p_2步长为2,让两个指针都从头结点往后走,如果存在环的话,两者肯定会再次相遇,因为在两个指针都进入环的时候,一个步长为2,一个步长为1,那就是说两个指针之间的距离每走一步就缩小1个单位,所以两个指针肯定会再次相遇。在相遇的时候,假设指针p1p_1走了xx步,那么p2p_2肯定走了2x2x步,因为每次p2p2都比p1p_1多走了一步。
同时,还会发现,这个p2p_2多走的xx步,肯定是多走在了换上,也就是说,xx是环的长度nn的整数倍,即有如下公式:
2x=x+k∗nk=1,2,3,…2x = x + k*n \qquad k = 1,2,3,\dots
p2p_2至少围着环转了一圈。
也就说,让一个指针指向环上的相遇点,一个指针指向头结点,同时以步长为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; } }
相关文章推荐
- Effective C++规定45 附加代码
- jQuery之call()方法的使用
- 【JS】浅谈匿名函数与闭包
- Now--Feature--Thinking
- 10个免费的响应式布局HTML5+CSS3模板
- #学习笔记#(16)ul li 二级下拉菜单-jQuery
- 从prototype.js中学习到的js封装
- 《Node.js In Action》笔记之流程控制
- JSTL 核心标签库 使用 (转)
- Famitracker 效果列表(Effect list)
- 初探nodejs创建web服务器
- json(转)
- Node.js(转) -- 临时来说还看不懂!
- 10012---JavaScript--保留关键字
- jQuery? 回归JavaScript原生API
- javascript转义字符
- javascript转义字符
- 20151113--JSTL
- jquery特效(8)—倒计时
- bootstrap心得