142. Linked List Cycle II
题目:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Note: Do not modify the linked list.
Follow up:
Can you solve it without using extra space?
给定一个链表的头指针,问你能不能只用常数的空间快速判断一个链表是不是有环,如果有环,返回环的起始位置。
代码:
不能用额外的空间,所以必须通过遍历,判断有没有环的存在。
经典的判断方法(百度很多哦):
对于判断链表是否有环,方法很简单,用两个指针,一开始都指向头结点,一个是快指针,一次走两步,一个是慢指针,一次只走一步,当两个指针重合时表示存在环了。
根据此方法:
如图,a代代表链表起始位置到环开始位置的距离;x代表环起始位置到快慢指针节点相遇点的距离;c代表环的长度。
假设慢指针和快指针在9处第一次相遇,于是又慢指针走的距离 s_slow=a+x,
快指针会多走一圈之后来追上慢指针,于是走的距离应该是 s_fast=a+n*c+x(快指针可能走了n圈)
因为快指针的速度是慢指针的2倍,所以距离s_fast=2*s_slow.于是有:a+x+nc = 2*(a+x) =>nc = a + x => a = (n-1)c+c-x
当慢指针走距离a时候,快指针走了n-1圈加c-x的距离。
所以如果把慢指针放回起点S,让他重启走完a距离,快指针从相遇点9继续走,他们第二次肯定会相遇在4,也就是环的起点。
因为满指针走完a的时间里,快指针刚好走完了整数圈加c-x的距离,肯定会停在圈的起点。
于是可以根据这个规律,求出环的起点:
java代码,不复杂,就是分别循环到两次,找到第二次相遇的点:
public ListNode detectCycle(ListNode head) {
if(head==null){return null;}
ListNode Slower = head;
ListNode Faster = head;
//循环到第一次相遇为止
while(Faster!=null && Slower != null){
Slower = Slower.next;
Faster = Faster.next;
if(Faster!=null){
Faster = Faster.next;
}
else{
return null;
}
System.out.println("Faster: "+Faster.val+" "+"Slower: "+Slower.val);
if(Slower==Faster){
Slower = head;
//循环到第二次相遇
while(Slower != Faster){
Slower = Slower.next;
Faster = Faster.next;
System.out.println("LittleCycle: Faster: "+Faster.val+" "+"Slower: "+Slower.val);
}
return Slower;
}
}
return null;
}
输出输出结果,构建如上图所示的环:
FirstCycle: Faster: 3 Slower: 2
FirstCycle: Faster: 5 Slower: 3
FirstCycle: Faster: 7 Slower: 4
FirstCycle: Faster: 9 Slower: 5
FirstCycle: Faster: 11 Slower: 6
FirstCycle: Faster: 5 Slower: 7
FirstCycle: Faster: 7 Slower: 8
FirstCycle: Faster: 9 Slower: 9
SecondCycle: Faster: 10 Slower: 2
SecondCycle: Faster: 11 Slower: 3
SecondCycle: Faster: 4 Slower: 4
环的起点: 4
问题代码逻辑不复复杂,但是解题思路很关键,也是百度学习了很久,当然测试也需要构建存在环的链表这种数据结构。
简单写下我的链表创建方法,也是凑了好久凑出来的,还在寻找好的方案:
先递归创建一个链表,然后把最后一个对象指向其中的一个(cycle=4),构建成环:)
本想直接递归创建一个带环的列表,但是很难在ListNode类中实现(至少我还没想出来:(),先这样用吧:
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
//递归调用makeListNode,创建列表。
ListNode head;
public ListNode(int[] array){
head=makeListNode(array,0);
}
//根据对象的值获取链表中某个对象
public ListNode getNode(int value){
ListNode temp = this.head;
while(temp.val != value){
temp = temp.next;
}
return temp;
}
/**
* 采用递归的方式创建链表
* 传入的是链表的数组表示法
* 构造后是链表的链表表示法
*/
public static ListNode makeListNode(int[] array,int index){
if(index < array.length){
int value=array[index];
ListNode t=new ListNode(value);
t.next=makeListNode(array,++index);
return t;
}
return null;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Solution a = new Solution();
int[] arr = {1,2,3,4,5,6,7,8,9,10,11};
int cycle = 4;
ListNode list = new ListNode(arr);
//把链表最后一位指向链表中第cycle个对象
if(cycle>0){
for (int i = 0;i<arr.length;i++){
if(cycle==arr[i]){
list.getNode(arr[arr.length-1]).next = list.getNode(cycle);
}
}
}
ListNode x = a.detectCycle(list.head);
if(x==null){
System.out.println("yes");
}
else{
System.out.println(x.val);
}
最后,提交结果:
142. Linked List Cycle II的更多相关文章
- 141. Linked List Cycle&142. Linked List Cycle II(剑指Offer-链表中环的入口节点)
题目: 141.Given a linked list, determine if it has a cycle in it. 142.Given a linked list, return the ...
- leetcode 141. Linked List Cycle 、 142. Linked List Cycle II
判断链表有环,环的入口结点,环的长度 1.判断有环: 快慢指针,一个移动一次,一个移动两次 2.环的入口结点: 相遇的结点不一定是入口节点,所以y表示入口节点到相遇节点的距离 n是环的个数 w + n ...
- 【算法分析】如何理解快慢指针?判断linked list中是否有环、找到环的起始节点位置。以Leetcode 141. Linked List Cycle, 142. Linked List Cycle II 为例Python实现
引入 快慢指针经常用于链表(linked list)中环(Cycle)相关的问题.LeetCode中对应题目分别是: 141. Linked List Cycle 判断linked list中是否有环 ...
- 142. Linked List Cycle II【easy】
142. Linked List Cycle II[easy] Given a linked list, return the node where the cycle begins. If ther ...
- Java for LeetCode 142 Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...
- 【LeetCode】142. Linked List Cycle II (2 solutions)
Linked List Cycle II Given a linked list, return the node where the cycle begins. If there is no cyc ...
- [LeetCode] 142. Linked List Cycle II 单链表中的环之二
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. To r ...
- (链表 双指针) leetcode 142. Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. To r ...
- 【LeetCode】142. Linked List Cycle II
Difficulty:medium More:[目录]LeetCode Java实现 Description Given a linked list, return the node where t ...
- [LeetCode] 142. Linked List Cycle II 链表中的环 II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...
随机推荐
- PHP多态的理解
多态性的一般定义为:同一个操作作用于不同的类的实例,将产生不同的执行结果.也即不同类的对象收到相同的消息时,将得到不同的结果.在实际的应用开发中,采用面向对象中的多态主要在于可以将不同的子类对象都当作 ...
- 【PHP面向对象(OOP)编程入门教程】20.PHP5接口技术(interface)
PHP与大多数面向对象编程语言一样,不支持多重继承.也就是说每个类只能继承一个父类.为了解决这个问题,PHP引入了接口,接口的思想是指定了一个实现了该接口的类必须实现的一系列方法.接口是一种特殊的抽象 ...
- 什么是H标签?H1,H2,H3标签?以及和strong标签使用的方法及重要性
大家都知道,seo的一个很重要的一点就是要把网站做的条理清晰,让搜索引擎很容易的读明白,这个条理清晰不仅体现在网站的物理路径,url等地 方.在<h1><h2><h3&g ...
- java中的方法重载与重写以及方法修饰符
1. 方法重载Overloading , 是在一个类中,有多个方法,这些方法的名字相同,但是具有不同的参数列表,和返回值 重载的时候,方法名要一样,但是参数类型和参数个数不一样,返回值类型可以相同,也 ...
- CSS伪选择器的使用-遁地龙卷风
分为伪元素选择器和伪类选择器两种,前者两个冒号,后者一个冒号,但是浏览器都看做一个冒号 1.a.::first-line 逐层匹配,直到有文本元素且结束改行为止 设置css属性word-break:b ...
- webpack 教程 那些事儿04-webpack项目实战分析
这节主要讲解真正项目用用到的 webpack配置问题,项目实战篇 就像我们不会完全做一个项目,不用别人的轮子一样.这个配置我们借用 vue-cli 搭建的配置来研究,因为它已经足够优秀. 有了前面的基 ...
- Windows上安装使用MongoDB(一)
首先下载MongoDB的Windows版本,从如下地址: https://www.mongodb.org/downloads. 我下载的msi版本,下载后安装即可,如我安装的盘符是:C:\Progra ...
- unity3d 关于断点下载和整个下载(用于更新)
转自:http://blog.csdn.net/yutyliu/article/details/24346459 string t = ""; //整体下载 IEnumerator ...
- Win10新版下virtualbox双击没有反应
百度virtualbox 第一个就是Oracle官网,点击download,点击相应的版本,下载后右键管理员权限去安装,
- FTP 传输中的主动模式和被动模式
最近做一个项目用到FTP和其它系统进行文件传输,结果在FTP网络连接的问题上花了很多时间,由于太久没搞多FTP,忘记了FTP不单单开放21端口,客户端采用不同连接模式对网络有不同.在此重温一下FTP的 ...