给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1 的范围内。
数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。
请找出数组中任意一个重复的数字。
注意:如果某些数字不在 0∼n−1 的范围内,或数组中不包含重复数字,则返回 -1;
样例
给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。
返回 2 或 3。

解法一:哈希表

遍历数组的同时,用哈希表存储数字出现的次数
时间复杂度O(n),空间复杂度O(n)

  1. class Solution {
  2. public:
  3. unordered_map<int, int> rec;
  4. int duplicateInArray(vector<int>& nums) {
  5. for (auto a: nums) {
  6. if (a >= 0 && a < nums.size())
  7. rec[a]++;
  8. else return -1;
  9. }
  10. for (auto it: rec) {
  11. if (it.second > 1) {
  12. return it.first;
  13. }
  14. }
  15. return -1;
  16. }
  17. };

解法二:交换

题目中说长度为n,数字在0~n-1的范围内,因此可以考虑将数字i交换到对应的位置i上去,一个萝卜一个坑
如果要交换到的位置上的数和当前数一致的话,说明重复
这样最多交换n次,时间复杂度O(n),空间复杂度O(1)
注意,如果某些数字不在 0∼n−1 的范围内必须得遍历完整个数组才能知道。先交换的话可能会提前发现重复的元素

  1. class Solution {
  2. public:
  3. int duplicateInArray(vector<int>& nums) {
  4. for (auto x: nums) {
  5. if (x < 0 || x >= nums.size()) {
  6. return -1;
  7. }
  8. }
  9. for (int i = 0; i < nums.size(); i++) {
  10. while (nums[i] != nums[nums[i]]) swap(nums[i], nums[nums[i]]); // 交换到对应位置
  11. if (nums[i] != i) return nums[i]; // 重复
  12. }
  13. return -1;
  14. }
  15. };