题目:

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练手 公约数和公倍数

    Problem D 公约数和公倍数 时间限制:1000 ms  |  内存限制:65535 KB   描述 小明被一个问题给难住了,现在需要你帮帮忙.问题是:给出两个正整数,求出它们的最大公约数和最小 ...

  2. C/C++开发者必不可少的15款编译器+IDE

    1)Best IDE for C/C++ –  kDevelop(http://kdevelop.org/) Kdevelop是一个专为C/C++及其他语言的开源扩展插件IDE.它基于KDevPlat ...

  3. 再谈select, iocp, epoll,kqueue及各种I/O复用机制

    原文:http://blog.csdn.net/shallwake/article/details/5265287 首先,介绍几种常见的I/O模型及其区别,如下: blocking I/O nonbl ...

  4. jbuilder的set!方法重构接口

    https://github.com/rails/jbuilder  的set!方法重构接口, 因为grape没法使用 jBuilder 的缓存,所以直接用 Rails 写 API (1)多个图片 i ...

  5. [HDU3709]Balanced Number

    [HDU3709]Balanced Number 试题描述 A balanced number is a non-negative integer that can be balanced if a ...

  6. MikroTik RouterOS防火墙与过滤详解

    MikroTik RouterOS能对包状态过滤:P2P协议过滤:源和目标NAT:对源MAC.IP地址.端口.IP协议.协议(ICMP.TCP.MSS等).接口.对内部的数据包和连接作标记.ToS 字 ...

  7. 17 任务调度相关类综述——Live555源码阅读(一)任务调度相关类

    这是Live555源码阅读的第二部分,包括了任务调度相关的三个类.任务调度是Live555源码中很重要的部分. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/ol ...

  8. 数据结构与算法实验题6.1 s_sin’s bonus byFZuer

    玩家从n 个点n-1 条边的图,从节点1 丢下一个小球,小球将由于重力作用向下落,而从小球所在点延伸出的每一条边有一个值pi 为小球通过该条边的概率(注意从同一个节点向下延伸的所有边的pi 的和可以小 ...

  9. CentOS 7 运行级别切换

    CentOS 7 之前的版本是通过 /etc/inittab 文件来定义系统运行级别: [sywu@wusuyuan ~]$ cat /etc/centos-release CentOS releas ...

  10. 深入浅出Mybatis-与Spring集成

    单独使用mybatis是有很多限制的(比如无法实现跨越多个session的事务),而且很多业务系统本来就是使用spring来管理的事务,因此mybatis最好与spring集成起来使用. 前置要求 版 ...