🚀蓝蓝计算机考研算法-day29数组中重复数字

146 阅读2分钟

Day29 2023/03/30

难度:简单

题目

在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组(2,3,1,0,2,5,3),那么对应的输出是2或者3。存在不合法的输入的话输出-1。

数据范围:0<=n<=10000 0<=n<=10000

进阶:时间复杂度On)On) 空间复杂度O(1)O(1)

示例

输入:(2,3,1,0,5,3)
输出:2
说明:2和3都是对的

思路

这道题可以使用哈希表来解决,时间复杂度为O(n),但需要额外的空间来存储哈希表。进阶要求时间复杂度为O(n),空间复杂度为O(1),可以使用数组本身作为哈希表,具体实现如下:

  1. 我们首先获取数组的长度 len,然后遍历数组中的每个数字。
  2. 如果当前数字不等于它的下标,那么就将它交换到正确的位置上,即交换到下标为它本身的位置上。
  3. 如果当前数字已经在正确的位置上,那么就说明这个数字重复了,返回它的值。如果遍历完成后没有找到重复数字,那么就返回-1。

关键点


  • 因为题目要求所有数字都在0到n-1的范围内,其中n为数组长度,所以才使用数组作为哈希表,这样不会出现数组下标溢出的情况!!!

算法实现


c++代码实现-找到重复数字

#include <iostream>
#include <vector>
using namespace std;

// 找出数组中的重复元素
int FindDuplicateElem(vector<int> &nums) {
  int len = nums.size(); // 数组长度
  for (int i = 0; i < len; i++) {
    // 如果当前数字没有再正确位置上,并且正确位置上已经存在正确元素了,说明该元素出现了重复
    if (nums[i] != i && nums[nums[i]] == nums[i]) {
      return nums[i]; // 返回重复元素
    }
    // 如果当前数字没有再正确位置上,但正确位置上并不存在正确元素了,说明该元素首次出现
    if (nums[i] != i && nums[nums[i]] != nums[i]) {
      swap(nums[i], nums[nums[i]]); // 将该元素放到它的正确位置下面
    }
  }
  return -1; // 没有正确元素
}

int main() {
  vector<int> nums = {2, 3, 1, 0, 2, 5, 3};
  int res = FindDuplicateElem(nums);
  cout << res << endl;
  return 0;
}
  • 时间复杂度 O(n)O(n)--- 遍历一次数组,其中n为数组长度。
  • 空间复杂度 O(1)O(1)--- 在原数组上操作,且仅含常数级变量。

总结

本题,虽然是常用的哈希法,但如果大家善用题目中一些细小的条件,往往会产生一些意想不到的效果!!!😁