floyd cycle detection 小总结

到目前为止做了200道leetcode,大多是按照从易到难的顺序,已经三次遇到完全不同的情景,但是采取floyd cycle detection 算法能够有效解决的问题的了。

floyd cycle detection 都是采用一快一慢两个指针,快的一次向前移动两步,慢的一次向前移动一步,这样快的每次都会多领先慢的一步。如果有环那么慢和快一定会相遇。

第一次是在链表的tag里遇到的:141.Linked List Cycle 要求判断是否有环 以及142. Linked List Cycle II 要求在判断是否有环,并在有环的情况下找到环开始的地方。

找环开始的地方的思路:由于fast每次多前进一个节点,在重合的时候slow走了a个节点,fast就多走了a节点,a也是圈的长度的k(k为正整数)倍,k与进环之前的链的长度有关。接下来,将一个指针放在fast和slow重合的位置,一个指针放在head,然后两个指针每次前进一个节点。由于一个指针领先另一个指针环的长度的整数倍,所以两个节点必会重合,且是在从head开始前进的指针刚进入环的时候即重合。

第二次遇到是Find the Duplicate Number, 问题描述如下:

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.

该问题时出现在binary search 这一tag中的,但是除了采取binary search 还可以采用floyd cycle detection

思路1:binary search 

时间复杂度:O(nlogn) 

视为二叉搜索问题时,第一遍搜索start = 1, end = n 小于等于mid = (start + end) / 2出现在整个数组中的次数,如果大于mid则说明这个重复的数在start和end之间,所以将end = mid, 否则不在范围内,将start = mid + 1。直到start == end时终止,此时找到了这个重复的数。

视为floyd cycledetection问题时,与142 问题类似。第一阶段是先要确定找到环存在,并找到fast==slow时候,领先了多少步。第二阶段,将其中一个重置到0位置,另一个保持(在环开始的位置),由于fast和slow能重合在这个位置相当于fast领先slow这一步数时,fast多在圈中走了圈长度的k倍(k为以正整数)。然后两个指针同步向前,直到找到环开始的位置,这个环开始的位置就是两个数的重复。可认为每个数组的索引是一个位置,而索引位置对应的值(value)即是指针指向的下一个位置。总共 n+1 个数,值为1~n,而数组的索引为 0:n,0不会出现在链表节点的next域,所以fast和slow两个指针都应该从0 开始。

初始条件

slow = 0,fast = nums[0]

每次前进:fast前进两步,slow前进一步

终止条件:fast == slow

可以参考:http://keithschwarz.com/interesting/code/?dir=find-duplicate

代码如下:

int findDuplicate3(vector<int>& nums)
{
    if (nums.size() > 1)
    {
        int slow = nums[0];
        int fast = nums[nums[0]];
        while (slow != fast)
        {
            slow = nums[slow];
            fast = nums[nums[fast]];
        }

        fast = 0;
        while (fast != slow)
        {
            fast = nums[fast];
            slow = nums[slow];
        }
        return slow;
    }
    return -1;
}

第三次遇到是在202.Happy number 问题,该问题描述如下:

Write an algorithm to determine if a number is "happy".

A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.

题目描述中已经提到了在环内循环。

在看到这个问题时首先想到的是采用hashset,每次将新产生的数放到set中,直到遇到重复的就退出循环。

也可以采用floyd cycle detection 算法。代码如下:

int digitSquareSum(int n) {
    int sum = 0, tmp;
    while (n) {
        tmp = n % 10;
        sum += tmp * tmp;
        n /= 10;
    }
    return sum;
}

bool isHappy(int n) {
    int slow, fast;
    slow = fast = n;
    do {
        slow = digitSquareSum(slow);
        fast = digitSquareSum(fast);
        fast = digitSquareSum(fast);
    } while(slow != fast);
    if (slow == 1) return 1;
    else return 0;
}

猜你喜欢

转载自www.cnblogs.com/rookielet/p/9102172.html