题目:

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的更多相关文章

  1. 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 ...

  2. leetcode 141. Linked List Cycle 、 142. Linked List Cycle II

    判断链表有环,环的入口结点,环的长度 1.判断有环: 快慢指针,一个移动一次,一个移动两次 2.环的入口结点: 相遇的结点不一定是入口节点,所以y表示入口节点到相遇节点的距离 n是环的个数 w + n ...

  3. 【算法分析】如何理解快慢指针?判断linked list中是否有环、找到环的起始节点位置。以Leetcode 141. Linked List Cycle, 142. Linked List Cycle II 为例Python实现

    引入 快慢指针经常用于链表(linked list)中环(Cycle)相关的问题.LeetCode中对应题目分别是: 141. Linked List Cycle 判断linked list中是否有环 ...

  4. 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 ...

  5. 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 ...

  6. 【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 ...

  7. [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 ...

  8. (链表 双指针) 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 ...

  9. 【LeetCode】142. Linked List Cycle II

    Difficulty:medium  More:[目录]LeetCode Java实现 Description Given a linked list, return the node where t ...

  10. [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 ...

随机推荐

  1. java 练手 谁是最好的Coder

    Problem A 谁是最好的Coder 时间限制:1000 ms  |  内存限制:65535 KB   描述 计科班有很多Coder,帅帅想知道自己是不是综合实力最强的coder. 帅帅喜欢帅,所 ...

  2. 部分LINUX系统由图形界面启动变更为命令行界面启动的方法

    背景: 图形界面很绚丽,但是现在并不需要图形界面,只需要命令行即可,所以要将图形界面自启动给关闭.    正文:   Centos:     更改文件/etc/inittab的其中一行    id:5 ...

  3. LR常用函数整理

    1,变量转参数lr_save_string("aaa","param"):将字符串"aaa"或者一个字符串变量,转变成LR的参数{param ...

  4. VM虚拟机下安装Centos7.0图文教程

    新建虚拟机的相关配置,LZ使用的是VMware workstation 10.2 ,(其它版本也ok的),配置见下图.. PS: 打开虚拟机之后,提示了一个小错误,LZ根据错误提示,到BIOS里面设置 ...

  5. canvas游戏小试:画一个按方向键移动的圆点

    canvas游戏小试:画一个按方向键移动的圆点   自己对canvas,但又有一颗做游戏的心TT.然后记录一下对canvas的学习吧,用一个按方向键控制的小圆点来做练习.(编程时用了一些es6的语法) ...

  6. 安装和配置VNC服务器的法则

    导读 这是一个关于怎样在你的 CentOS 7 上安装配置VNC服务的教程.当然这个教程也适合 RHEL 7 .在这个教程里,我们将学习什么是 VNC 以及怎样在 CentOS 7 上安装配置VNC ...

  7. iOS 开发 初级:应用内购买 In-App Purchase

    http://blog.csdn.net/songrotek/article/details/8680415 现在有很多应用都使用了In-App Purchase,虽然对于很多用户来说,可能并不喜欢甚 ...

  8. [转载]Web 研发模式演变

    原文链接:https://github.com/lifesinger/blog/issues/184 前不久徐飞写了一篇很好的文章:Web 应用的组件化开发.本文尝试从历史发展角度,说说各种研发模式的 ...

  9. hdu1536&&hdu3023 SG函数模板及其运用

    S-Nim Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status ...

  10. 前端之常用标签和CSS初识

    外层div的宽度是100%,就是视口的大小,当视口被拉窄到小于内层div的宽度980px时,比如800px,此时 外层div宽度为800px,内层div宽度依然为980px,而css中只设置了外层di ...