[LeedCode]Find the Duplicate Number/Linked List Cycle II

看到一个时间复杂度为O(n)的解法,觉得很有意思。记录一下。

题目:
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.

Note:
You must not modify the array (assume the array is read only).
You must use only constant, O(1) extra space.
Your runtime complexity should be less than O(n2).
There is only one duplicate number in the array, but it could be repeated more than once.
Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.

Subscribe to see which companies asked this question.

O(n)时间复杂度代码:

public class Solution {
    public int findDuplicate(int[] nums) {
        int slow = 0;
        int fast = 0;
        int finder = 0;

        while (true){
            slow = nums[slow];
            fast = nums[nums[fast]];
            if (slow == fast)
                break;
        }
        while (true)
        {
            finder = nums[finder];
            slow = nums[slow];
            if (slow == finder)
                return slow;
        }
    }
}

解析:
解析引用自@LuckyPants said in Share my solution O(N) time O(1) space. 12 ms:
来源:https://discuss.leetcode.com/topic/29716/share-my-solution-o-n-time-o-1-space-12-ms/16
这里写图片描述

k 是进入循环前的长度,
c 是循环的长度
A 是循环入口

从slow和fast开始移动到他们相遇,设slow走过的距离为X
fast走过的距离为2X,相遇时有X = 2X - X = n*c .
(ps: n是一个正整数且易知 n*c >= k)

n*c - k = 相遇时过A点距离
所以slow和fast相遇时位置和A入口的距离应为(n*c - k)%c

为了从当前位置再次到达A点,即(n*c - k + k)%c = 0
我们用一个从0开始的finder,以和slow一样的速度到达A,距离为k,slow也走这样长的距离,因而得到入口点A。

圆的入口不止一个,这意味着至少两个数字不同的索引数组中有相同的值,slow和finder索引记录的就是重复的数字。


同样原理的应用:Linked List Cycle II

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?

Subscribe to see which companies asked this question.

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {

        if (head == null||head.next==null || head.next.next==null) return null;
        ListNode slow = head.next;
        ListNode fast = head.next.next;
        ListNode k = head;

        while (slow!=fast)
        {
            if(fast.next==null || fast.next.next==null)
                return null;
            slow = slow.next;
            fast = fast.next.next;
        }
        while (k!=slow)
        {
            k = k.next;
            slow = slow.next;
        }
        return k;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章