zoukankan      html  css  js  c++  java
  • cc150 Chapter 2 | Linked Lists 2.6 Given a circular linked list, implement an algorithm which returns node at the beginning of the loop.

    2.6Given a circular linked list,  implement an algorithm which returns the node at the beginning of the loop.

      快指针和慢指针一起在头指针开始移动,快指针每次移动两步,慢指针每次移动一步,直到相遇, 相遇后,把慢指针指向头指针,两个指针一起往后移动一步。直到相遇,相遇的地方就是循环的开始(如果相遇,说明是有循环的节点,这时快指针走的路程是慢指针的两倍,快:开始的k距离,和一圈(或者n圈)循环,和慢指针走过的循环圈的路部分长度这三部分相加。。。

    看图:

    慢指针走的距离是 开始没进循环的k距离慢指针走过的循环圈的路部分长度 这两部分相加),那么 快指针的长度是:K+慢在循环圈里的距离+ 满圈的长度*n圈; 慢指针的长度是:K+慢在循环圈里的距离,同时,因为快指针每次走两步,慢指针每次走一步,所以 快的长度等于慢长度的2倍:得到:(K+慢在循环圈里的距离+ 满圈的长度*n圈)=2*(K+慢在循环圈里的距离)所以:

    上式子可以变成:K+慢在循环圈里的距离+ 满圈的长度*n圈 =K+慢在循环圈里的距离+K+慢在循环圈里的距离。

    所以可以得到:满圈的长度*n圈 =K+慢在循环圈里的距离;

      如果n是1, 那么k的长度就是等于现在相遇地方到循环开始的地方。就是k到循环开始的地方和相遇地方到循环开始的地方。。

     如果 n是2,那么k到循环开始的地方就是,循环一圈加相遇地方到循环开始的地方。

     所以,k到循环开始的地方和相遇地方到循环开始的地方。

     所以,一个指针在原地,一个指针在开始的地方,都往前走,相遇的那个点就是循环开始的地方。

     1 public class Circ6 {
     2     static class LinkNode {
     3         int val;
     4         LinkNode next;
     5 
     6         LinkNode(int x) {
     7             val = x;
     8             next = null;
     9         }
    10     }
    11 
    12     public static LinkNode FindBeginning(LinkNode head) {
    13         LinkNode slowp = head;
    14         LinkNode fastp = head;
    15 
    16         while (fastp != null && fastp.next != null) {
    17             fastp = fastp.next.next;
    18             slowp = slowp.next;
    19             if (fastp == slowp) {
    20                 break;
    21             }
    22         }
    23         if (fastp == null || fastp.next == null) {
    24             return null;
    25         }
    26         slowp = head;
    27         while (slowp != fastp) {
    28             slowp = slowp.next;
    29             fastp = fastp.next;
    30         }
    31         return slowp;
    32     }
    33 }

    网上还看到另一个解题方法:

    就是用hashSet,存每一个节点,如果set里存在这个节点,就返回这个节点。

    public LinkNode firstNodeInCircle1(LinkNode head) {
            if (head == null || head.next == null)
                return null;
    
            Set<LinkNode> hashSet = new HashSet<LinkNode>();
            while (head != null) {
                if (hashSet.contains(head)) {
                    return head;
                } else {
                    hashSet.add(head);
                    head = head.next;
                }
            }
            return null;
        }

    Reference:

    http://www.hawstein.com/posts/2.5.html

    http://www.jyuan92.com/blog/careercup2_6-first-node-in-circle-linkedlist/

    https://github.com/1094401996/CareerCup/blob/master/Chapter02/src/twodot6/Circular.java

  • 相关阅读:
    UEFI手札
    ARM非对齐访问和Alignment Fault
    PCIE手札
    开始→运行(cmd)命令大全
    关于C#静态构造函数的几点说明
    网址
    python并发编程之多进程理论部分
    第九篇:网络编程
    第八篇:异常处理
    第七篇:面向对象高级
  • 原文地址:https://www.cnblogs.com/hewx/p/4492189.html
Copyright © 2011-2022 走看看