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

方法1:利用hash表特性,时间复杂度O(n),空间复杂度O(n)

思路:由于n个数字的范围已知,都在[0,n-1]之间,所以建立一个长度为n的数组hash,遍历输入数组,将hash数组中下标对应原数组数值的+1,所以hash数组的下标即为输入数组的值,hash数组的值即为对应下标表示的数的个数

#include<iostream>
#include<vector>
using namespace std;
/*
测试用例:空,只含一个数,没有重复,正常重复。
思路:因为数字范围是固定的[0,n-1],所以可以考虑哈希表
*/
bool duplicate(int numbers[], int length, int* duplication) {
    if (length <= 0 || numbers == NULL)
        return false;
    vector<int> hash(length,0);
    for (int i = 0; i < length; i++)
    {
        hash[numbers[i]]++;
    }
    for (int i = 0; i < length; i++)
    {
        if (hash[i] > 1)
        {
            *duplication = i;
            return true;
        }
    }
    return false;
}

int main()
{
    int numbers[] = {2,1,3,1,4};
    int length = sizeof(numbers) / sizeof(numbers[0]);
    int duplication;
    cout << duplicate(numbers, length, &duplication) << endl;
    cout << duplication << endl;
    return 0;
}

方法2:hash表改进,,时间复杂度O(n),空间复杂度O(n)

算法步骤:

  1. 开辟一个长度为n的vector<bool>, 初始化为false</bool>
  2. 遍历数组,第一次遇到的数据,对应置为true
  3. 如果再一次遇到已经置为true的数据,说明是重复的。返回即可。
#include<iostream>
#include<vector>
#include<map>
using namespace std;
bool duplicate(int numbers[], int length, int* duplication) {
    if (length <= 0 || numbers == NULL)
        return false;
    vector<bool> hash(length,false);
    for (int i = 0; i < length; i++)
    {
        if (!hash[numbers[i]])
            hash[numbers[i]] = true;
        else
        {
            *duplication = numbers[i];
            return true;
        }        
    }
    return false;
}

int main()
{
    int numbers[] = {1,2,4,4,3};
    int length = sizeof(numbers) / sizeof(numbers[0]);
    int duplication=0;
    cout << duplicate(numbers, length, &duplication) << endl;
    cout << duplication << endl;
    return 0;
}

超级方法:时间复杂度O(n),空间复杂度O(1)

具体文字思路看书

#include<iostream>
#include<vector>
#include<map>
using namespace std;
bool duplicate(int numbers[], int length, int* duplication) {
    if (length <= 0 || numbers == NULL)
        return false;
    int i = 0, m = numbers[i];
    for (int i = 0; i < length; i++)
    {
        while (numbers[i]!=i)
        {
            if (numbers[i] == numbers[numbers[i]])
            {
                *duplication = numbers[i];
                return true;
            }
            swap(numbers[i], numbers[numbers[i]]);
        }
    }
    return false;
}

int main()
{
    int numbers[] = {1,2,4,4,3};
    int length = sizeof(numbers) / sizeof(numbers[0]);
    int duplication=0;
    cout << duplicate(numbers, length, &duplication) << endl;
    cout << duplication << endl;
    return 0;
}