LeetCode 287 Find the Duplicate Number
思路
-
这一题可以将各位置的值作为索引,去找到下一个位置的值。题中数组为[1,3,4,2,2]。因此有nums[0] = 1, nums[1] = 3, nums[2] = 4, nums[3] = 2, nums[4] = 2。那么可以生成这样一个链表:0->1->3->2<->4。重复的元素不做区分。那么这一题就转化为找到链表中环的起点。
-
使用二分查找,因为原数组并未排序,因此在更新二分查找的范围前,先要遍历整个数组。对于mid,统计数组中小于mid的元素的个数,如果如果个数大于mid,说明重复的元素在左边,否则位于右边。
代码
方法1
class Solution {
public:
int findDuplicate(vector<int>& nums) {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int slow = nums[0], fast = nums[nums[0]];
while (slow != fast) {
slow = nums[slow];
fast = nums[nums[fast]];
}
fast = 0;
while (slow != fast) {
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
};
方法2
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int left = 0, right = nums.size() - 1;
while (left < right) {
int mid = left + (right - left) / 2;
int cnt = 0;
for (const auto &n : nums) {
if (n <= mid) ++cnt;
}
if (cnt > mid) right = mid;
else left = mid + 1;
}
return left;
}
};
总结
对于此类数组元素的取值范围可以变化到[0, nums.size())范围内的题目,可以将元素的值作为索引,从而形成一个链表。又或者搭配二分查找等其他方法,比如将元素值修改为负数,在需要其作为索引时,取绝对值即可。