题目:

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. 关于COOKIE学习的一二

    index.php <?php setcookie("name","dalisng",time()+3600); setcookie("addr ...

  2. cf#305 Mike and Foam(容斥)

    C. Mike and Foam time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  3. MVC中下拉列表绑定方法

    方法一: 前端 @Html.DropDownListFor(a=>a.acate,ViewBag.CateList as IEnumerable<SelectListItem>) 后 ...

  4. NoSuchMethodException问题总结

    1.编译异常,这个很容易发现并解决: method真的没有 替换jar包没有clean project. 2.编译正常,运行报错 这是一个遇到之后让人纳闷的异常,脑袋不转弯的时候真的容易被卡住.这时只 ...

  5. webpack 教程 那些事儿06-gulp+webpack多页

    本篇主要讲述用gulp+webpack构建多页应用 折腾到现在,项目还必须要进行,.vue文件必须要加载,也就是webpack必须引入.时间不多了,抛弃上个方案之后,只能牺牲热加载性能,用gulp+w ...

  6. webpack 教程 那些事儿01-webpack是什么

    文章目录 1. 为什么引入webpack? 2. webpack到底是什么? 3. webpack的工作流程理念 4. webpack的使用 4.1. install webpack 5. 分享源码d ...

  7. 【转】phpcms-v9中关于模型的理解

    PHPCMS v9 模型概念 一.什么是模型? 模型是系统知识的抽象表示.我们不能仅仅通过语言来描述一个系统,也不能仅仅通过记忆来记录关于系统的知识.知识是通过某种媒介来表达的,这种媒介所表达的内容就 ...

  8. 目前主流的Android定位有如下几种:

    1.通过GPS模块 GPS方式准确度是最高的,但是它的缺点也非常明显:1,比较耗电:2,绝大部分用户默认不开启GPS模块:3,从GPS模块启动到获取第一次定位数据,可能需要比较长的时间:4,室内几乎无 ...

  9. maven引入jar包时,一个jar的引入错误,会导致后来的jar包的引入。

    maven引入本jar包时,引入失败. 问题是另一个jar没有引入正确.

  10. 最牛X的GCC 内联汇编

    导读 正如大家知道的,在C语言中插入汇编语言,其是Linux中使用的基本汇编程序语法.本文将讲解 GCC 提供的内联汇编特性的用途和用法.对于阅读这篇文章,这里只有两个前提要求,很明显,就是 x86 ...