LeetCode 287 Find the Duplicate Number

259 阅读1分钟

LeetCode 287 Find the Duplicate Number

思路

  1. 这一题可以将各位置的值作为索引,去找到下一个位置的值。题中数组为[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。重复的元素不做区分。那么这一题就转化为找到链表中环的起点。

  2. 使用二分查找,因为原数组并未排序,因此在更新二分查找的范围前,先要遍历整个数组。对于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())范围内的题目,可以将元素的值作为索引,从而形成一个链表。又或者搭配二分查找等其他方法,比如将元素值修改为负数,在需要其作为索引时,取绝对值即可。