zoukankan      html  css  js  c++  java
  • [LeetCode#142]Linked List Cycle II

    The question:

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

    Follow up:
    Can you solve it without using extra space?

    The analysis:

    This question is very interesting, but a little tricky. 
    key idea: Use the proper distance relationship analysis to get the clear idea and answer. But you need very careful about the corner cases.
    Classic method: use two pointers.
    1. walker pointer: each time, the pointer move one step;
    2. runner pointer: each time, the pointer move two steps.
    As if there is a circle in the list, the walker pointer and runner pointer must would meet each other.
    while (runner.next != null && runner.next.next != null) {
        walker = walker.next;
        runner = runner.next.next;
        if (walker == runner) {
            is_cycle = true;
            break;
        }
    }
    How to get the node where the cycle starts?
         a     start      b
    ------------o----------------o(collision point)
                |                |
                |                |
                |----------------|                
                         c
    since the runner's pace is the twice speed of a, we must meet the condition:
    a+n(b+c)+b = 2(a+b) 
    we could infer:
    n(b+c) = a+b  ===> n(b+c)-b = a
    This means that if one pointer start from the head, and one pointer start from the collision point, and they are in the same pace, they would meet each other at the start point.
    walker = head;
    while (walker != runner) {
        walker = walker.next;
        runner = runner.next; //the runner's pace is adjusted!
    }
    return walker;
    
    Note: there is a hidden buggy condition. 
    If we write the loop in following way: 
    walker = head;
    while (runner.next != null) {
        walker = walker.next;
        runner = runner.next; //the runner's pace is adjusted!
        if (walker == runner)
            break;
    }
    return walker;
    
    The fragment seems to be right at first sight. However, it could not tackle the corner case:
    node1 -> node2 -> node1
    At this case, the collision point would be node1. it means we start walker and runner at the same position, it would lead to walker == runner at node2, which would result in the wrong answer. 
    A little change in code would solve the corner case:
    walker = head;
    while (walker != runner) {
        walker = walker.next;
        runner = runner.next; //the runner's pace is adjusted!
    }
    return walker;

    My solution:

    public class Solution {
        public ListNode detectCycle(ListNode head) {
            if (head == null)
                return null;
            ListNode walker = head;
            ListNode runner = head;
            boolean is_cycle = false;
            while (runner.next != null && runner.next.next != null) {
                walker = walker.next;
                runner = runner.next.next;
                if (walker == runner) {
                    is_cycle = true;
                    break;
                }
            }
            if (is_cycle != true) //if there is no cycle exist.  
                return null;
            walker = head;
            while (walker != runner) {
                walker = walker.next;
                runner = runner.next; //the runner's pace is adjusted!
            }
            return walker;
        }
    }
  • 相关阅读:
    Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) C. Success Rate
    Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) B. T-Shirt Hunt
    go 读取数据库所有表数据显示到网页(便于测试时看)
    go 文件上传
    go 文件服务(读取须权限)
    vps git无法clone DNS解析错误
    go 自己封的postgresql连接池操作包
    看 迪杰斯特拉(Dijsktra)算法体会
    Floyd算法(弗洛伊德算法) 百度百科
    Constructing Roads In JGShining's Kingdom
  • 原文地址:https://www.cnblogs.com/airwindow/p/4235130.html
Copyright © 2011-2022 走看看