[LeetCode] 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.
Example 1:
Input: [1,3,4,2,2]
Output: 2
Example 2:
Input: [3,1,3,4,2] Output: 3
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.
這道題給了我們n+1個數,所有的數都在[1, n]區域內,首先讓我們證明必定會有一個重複數,這不禁讓我想起了小學華羅庚奧數中的抽屜原理(又叫
解法一:
class Solution { public: int findDuplicate(vector<int>& nums) { int left = 0, right = nums.size(); while (left < right){ int mid = left + (right - left) / 2, cnt = 0; for (int num : nums) { if (num <= mid) ++cnt; } if (cnt <= mid) left = mid + 1; else right = mid; } return right; } };
經過熱心網友的留言提醒還有一種O(n)的解法,並給了參考帖子,發現真是一種不錯的解法,其核心思想快慢指標在之前的題目Linked List Cycle II中就有應用,這裡應用的更加巧妙一些,由於題目限定了區間[1,n],所以可以巧妙的利用座標和數值之間相互轉換,而由於重複數字的存在,那麼一定會形成環,我們用快慢指標可以找到環並確定環的起始位置,確實是太巧妙了!
解法二:
class Solution { public: int findDuplicate(vector<int>& nums) { int slow = 0, fast = 0, t = 0; while (true) { slow = nums[slow]; fast = nums[nums[fast]]; if (slow == fast) break; } while (true) { slow = nums[slow]; t = nums[t]; if (slow == t) break; } return slow; } };
這道題還有一種位操作Bit Manipulation的解法,也十分的巧妙。思路是遍歷每一位,然後對於32位中的每一個位bit,我們都遍歷一遍從0到n-1,我們將0到n-1中的每一個數都跟bit相‘與’,若大於0,則計數器cnt1自增1。同時0到n-1也可以當作nums陣列的下標,從而讓nums陣列中的每個數字也跟bit相‘與’,若大於0,則計數器cnt2自增1。最後比較若cnt2大於cnt1,則將bit加入結果res中。這是為啥呢,因為對於每一位,0到n-1中所有數字中該位上的1的個數應該是固定的,如果nums陣列中所有數字中該位上1的個數多了,說明重複數字在該位上一定是1,這樣我們把重複數字的所有為1的為都累加起來,就可以還原出了這個重複數字,參見程式碼如下:
解法三:
class Solution { public: int findDuplicate(vector<int>& nums) { int res = 0, n = nums.size(); for (int i = 0; i < 32; ++i) { int bit = (1 << i), cnt1 = 0, cnt2 = 0; for (int k = 0; k < n; ++k) { if ((k & bit) > 0) ++cnt1; if ((nums[k] & bit) > 0) ++cnt2; } if (cnt2 > cnt1) res += bit; } return res; } };
類似題目:
參考資料: