287. Find the Duplicate Number 數組中的重複數

Note:和《劍指offer》面試題3:數組中的重複數字 類似

解法一:映射找環法O(n)

我當時想到的解法,要麼時間複雜度不合要求,要麼空間複雜度不合要求,看了這道題的discussion區,結合兩個回答,總算是明白了這道題該怎麼解比較簡單。
兩個回答的鏈接:
- Java O(n) time and O(1) space solution. Similar to find loop in linkedlist.
- My easy understood solution with O(n) time and O(1) space without modifying the array. With clear explanation.


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

代碼如下:

public int findDuplicate(int[] nums) {
        if (nums.length > 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;
    }

思路
例如下面這個數組:

index: 0 1 2 3 4 5
value: 1 2 3 2 1 4

因爲數組值的特殊性,所以配合其索引index,可以形成index的圖,又因爲有重複的數字存在,所以圖的某個部分會形成一個circle,circle的入口爲重複的那個數。

該數組索引形成的圖爲:
index形成的圖
第一部分,如果安排一個slow的index(每次一步)和fast的index(每次兩步),它們走着最終會在circle中一直循環出不去,但遲早會相遇。類似數學題中的,甲乙以不同速度同向出發,最終快的會趕上慢的。然而,相遇停下的地方不一定是circle入口。
第二部分,一個index從0出發,一個從停下的位置出發,步長都爲1。假設circle之前的直線長度爲m(不包括circle入口),circle長度爲n,相遇點在circle的第k處(circle入口爲第1處),則fast走過的路程爲m + i*n + k,slow走過的路程爲m+j*n+k,二者所花時間相等,速度已知。可得,等式(m + i*n + k)/2 = m+j*n+k ==> m = (i-2j)*n - k;(i-2j)不爲0,令s = i - 2j,s爲正整數,則m = sn - k , m = (s-1)n + (n - k)。slow正在k點,這個特殊關係使得如果將fast放回0點,當fast到達circle的入口時走了m步,而slow走了(n - k)又繞了(s-1)n圈回到了circle的入口處,它們的相遇點正好是入口。

解法二:二分法O(n*lgn)

利用鴿巢原理的二分解法
上面這個鏈接解釋的很清楚了,一看就懂。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章