#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
// 长度为n的数组,每个数值都在1~n范围内,找出其中重复的元素
// 方法一:
// hash表实现(set) 空间复杂度较高
// 或者组数标记,出现且为0置1,为1则说明存在
vector<int> find_dup1(int arr[], int n){
unordered_set<int> s;
vector<int> res;
if (n == 0 || n == 1) {
return res;
}
for (int i = 0; i < n; ++i){
if (!s.count(arr[i])){
s.insert(arr[i]);
}
else{
res.push_back(arr[i]);
}
}
return res;
}
// 方法二
// 基数排序的思想,但是限制是只能找到一个重复元素,否则输出结果会重复
int find_dup2(int arr[], int n){
if (n == 0 || n == 1) return -1;
int i = 0;
while (i < n){
if (arr[i] == i+1){
++ i;
//continue;
}
else{
if (arr[i] == arr[arr[i]-1]){
return arr[i];
}
else{
// void swap(int &a, int &b);
swap(arr[i], arr[arr[i]-1]);
}
}
}
return -1;
}
//方法三
// 思路:遍历数组,将(元素-1)作为下标访问对应元素,并将该元素设置为相反数
// 则下次有重复元素的时候(元素-1)作为下标访问对应元素的时候,该元素已经为负
// 则找到了重复元素
// 注意,将元素作为下标访问时,应该取绝对值,因为可能为负,无法作为索引
vector<int> find_dup3(vector<int> nums){
vector<int> res;
int n = nums.size();
if (n == 0 || n == 1) return res;
for (int i = 0; i < n; ++i){
int j = nums[i];
j = abs(j);
if (nums[j-1] > 0){
nums[j-1] = -nums[j-1];
}
else{
res.push_back(j);
}
}
return res;
}
int main()
{
int arr[7] = {1,3,4,3,2,2,6};
// 一
vector<int> res1 = find_dup1(arr, 7);
//int n = res.size();
for (size_t i = 0; i < res1.size(); ++i){
cout<<res1[i]<<" ";
}
cout<<endl;
// 二
cout<<find_dup2(arr, 7)<<endl;
// 三
vector<int> nums(arr, arr+7);
vector<int> res3 = find_dup3(nums);
for (size_t i = 0; i < res3.size(); ++i){
cout<<res3[i]<<" ";
}
cout<<endl;
return 0;
}