1. 程式人生 > >LeetCode 287. Find the Duplicate Number (找到重復的數字)

LeetCode 287. Find the Duplicate Number (找到重復的數字)

ant pre ast web integer lan algorithm xtra 理論

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:

  1. You must not modify the array (assume the array is read only).
  2. You must use only constant, O
    (1) extra space.
  3. Your runtime complexity should be less than O(n2).
  4. There is only one duplicate number in the array, but it could be repeated more than once.


題目標簽:Array, Binary Search, Two Pointers

  題目給了我們一個nums array, 讓我們找到其中的重復數字。因為這一題有4個條件,所以有難度。1. 要求我們不能改動array;2. 只能用O(1)空間;3. 時間要小於O(n^2);4. 只有一個重復的數字,但是它可以出現最少1次。

  方法1:

    利用binary search。

    題目給的數字是在 [1, n] 之間, array 的size 是 n+1。所以肯定有一個數字會至少出現2次。

    分析一下:  

      如果n 是5,那麽就會有1 2 3 4 5 一共5個數字的可能,而array size 是6,那麽其中一個數字肯定會至少出現兩次。

      如果沒有重復的數字,小於等於1的數字 出現的次數 等於 1;

                小於等於2的數字 出現的次數 等於 2;

                ... 同理3;4;5。

      如果有重復的數字,如果重復的是1,那麽 小於等於1的數字 出現的次數 肯定大於1;

      基於這個理論,我們可以在1 2 3 4 5 選出一個 mid, 遍歷array來count 小於等於mid 的數字個數 小於等於 它自己mid 還是 大於 mid?

          如果count 小於等於mid, 說明 1 到 mid 這些數字 沒有重復項, 重復項在 右半邊 mid 到n, 所以縮小到右半邊繼續搜索;

          如果count 大於mid, 說明 1 到 mid 這些數字中 有重復項,縮小到 左半邊繼續搜索。

Java Solution:

Runtime beats 28.13%

完成日期:09/13/2017

關鍵詞:Array, Binary Search

關鍵點:如果從1到n中 有重復項,那麽必然有一個數字出現的次數至少是2次

 1 class Solution 
 2 {
 3     public int findDuplicate(int[] nums) 
 4     {
 5         /* Solution 1: binary search */
 6         int low = 1, high = nums.length - 1;
 7         
 8         while(low <= high)
 9         {
10             int mid = low + (high - low) / 2;
11             int cnt = 0;
12             
13             for(int a: nums)
14             {
15                 if(a <= mid)
16                     cnt++;
17             }
18             
19             if(cnt <= mid) // meaning duplicate is on the right side
20                 low = mid + 1;
21             else // if cnt > mid, meaning duplicate is on the left side
22                 high = mid - 1;
23                 
24         }
25         
26         return low;
27     }
28 }

參考資料:

http://bookshadow.com/weblog/2015/09/28/leetcode-find-duplicate-number/

  方法2:O(n),利用slow 和fast 雙指針 (還沒搞懂,暫時放著吧)

                

LeetCode 算法題目列表 - LeetCode Algorithms Questions List

LeetCode 287. Find the Duplicate Number (找到重復的數字)