zoukankan      html  css  js  c++  java
  • leetcode 457. Circular Array Loop

    先回顾一下链表的类似问题

    leetcode 141 判定链表是否有环

    慢指针slowPtr每次后移1个结点。快指针fastPtr每次后移2个结点

       function isLinkedListContainsLoop( head){
            if(head==null){
                return false;
            }
            let slowPtr=head;
            let fastPtr=head;
            while(slowPtr.next!=null && fastPtr.next.next!=null){
                slowPtr=slowPtr.next;
                fastPtr=fastPtr.next.next;
                if(slowPtr==fastPtr){
                    return true;
                }
            }
            return false;
        }
    

    LeetCode 142 找出环的入口点(起点)

    当fast按照每次2步,slow每次一步的方式走,发现fastPtr和slowPtr重合,确定了单向链表有环路。接下来,让slowPrt回到链表的头部,然后slowPtr和fastPtr各自从自己的位置(fastPtr从两个指针相遇的位置position出发)沿着链表出发,每次步长1,那么当fastPtr和slowPtr再次相遇的时候,就是环路的入口了。

    function findLinkedListLoopBegin(head) {
                if (head == null) {
                    return null;
                }
                let slowPtr = head;
                let fastPtr = head;
                let isLinkedListContainsLoop = false;
                while (slowPtr.next != null && fastPtr.next.next != null) {
                    slowPtr = slowPtr.next;
                    fastPtr = fastPtr.next.next;
                    if (slowPtr == fastPtr) {
                        isLinkedListContainsLoop = true;
                        break;
                    }
                }
                if (isLinkedListContainsLoop) {
                    slowPtr = head;
                    let count = 1
                    while (slowPtr == fastPtr) {
                        slowPtr = slowPtr.next;
                        fastPtr = fastPtr.next;
                        count++
                    }
                    return slowPtr;
                }
                return null;
            }
    

    设环长为n,非环形部分长度为m,当第一次相遇时显然slow指针行走了 m+An+k(A表示slow行走了A圈。附:An 是因为如果环够大,则他们的相遇需要经过好几环才相遇)。fast行走了 m+B*n+k。

    上面我们说了slow每次行走一步,fast每次行走两步,则在同一时间,fast行走的路程是slow的两倍。假设slow行走的路程为S,则fast行走的路程为2S。

    用fast减去slow可得:

    S=(B-A)*n

    很显然这意味着当slow和fast相遇时他们走过的路程都为圈长的倍数。

    接下来,将slow移动到起点位置,如下图:

    然后每次两个指针都只移动一步,当slow移动了m,即到达了环的起点位置,此时fast总共移动了 2S+m。 考虑到S为环长的倍数,可以理解为:fast先从链表起点出发,经过了m到达环的起点,然后绕着环移动了几圈,最终又到达环的起点,值为2S+m。所以fast最终必定处在环的起点位置。即两者相遇点即为环的起点位置。

    衍生问题2,求环的大小(长度)

    当fast按照每次2步,slow每次一步的方式走,发现fastPtr和slowPtr重合,确定了单向链表有环路。接下来,让slowPrt不动,fast 绕着环移动,每次移动一步,计数count加1,当两指针再次相遇时,count即是环的大小

    回归原题,也是用快慢节点

    function circularArrayLoop(nums) {
                let n = nums.length;
                if (n <= 1) {
                    return false
                }
                function getNext(i) {
                    return (i + nums[i] + n) % n
                }
    
                for (let i = 0; i < n; i++) {
                    let slow = i, fast = getNext(i);
                    //确保总是朝着一个方向前进
                    while (nums[slow] * nums[i] > 0 && nums[fast] * nums[i] > 0) {
                        if (slow == fast) {
                            //判断是否只有一个元素
                            if (slow == getNext(slow)) {
                                break;
                            }
                            return true;
                        }
                        slow = getNext(slow);
                        fast = getNext(fast);//快指针每次走两步
                        if (nums[fast] * nums[i] < 0) {//如果方向反了
                            break;
                        }
                        fast = getNext(fast);
                    }
                }
                return false;
            }
    
            console.log(circularArrayLoop([2, -1, 1, 2, 2]))
            console.log(circularArrayLoop([-1, 2]))
            console.log(circularArrayLoop([-2, 1, -1, -2, -2]))
    
    
  • 相关阅读:
    java中复制图片
    java中复制图片
    java中替换文件内容
    java中替换文件内容
    java中替换文件内容
    java中复制文本文件
    mac 地址分配
    data standardization
    Orthogonal Least Squares Learning Algorithm for Radial Basis Function Networks
    算法设计 mac 字符串 标识 n维度 2 3维度 字符串 标识值 特征值
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/12159239.html
Copyright © 2011-2022 走看看