思路一:用unordered_map保存即可
bool duplicate(int nums[],int len,int* duplication){
if(nums==nullptr||len<=0) return false;
for(int ii=0;ii<len;ii++){
if(nums[ii]<0||nums[ii]>=len) return false;
}
unordered_map<int,int> map;
map.reserve(len);//重新指定容量
for(int ii=0;ii<len;ii++){
if(map.find(nums[ii])==map.end()){
map.insert({nums[ii],1});//注意中括号
}else{
*duplication=nums[ii];
return true;
}
}
return false;
}
思路二:用 vector来减少内存,降低内存复杂度
bool duplicate1(int nums[],int len,int* duplication){
if(nums==nullptr||len<=0) return false;
for(int ii=0;ii<len;ii++){
if(nums[ii]<0||nums[ii]>=len) return false;
}
vector<bool> vec(len,false);
for(int ii=0;ii<len;ii++){
if(vec[nums[ii]]==false){
vec[nums[ii]]=true;//注意中括号
}else{
*duplication=nums[ii];
return true;
}
}
return false;
}
思路三:不占用任何空间的一种做法
bool duplicate(int nums[],int len,int* duplication){
if(nums==nullptr||len<=0) return false;
for(int ii=0;ii<len;ii++){
if(nums[ii]<0||nums[ii]>=len) return false;
}
for(int ii=0;ii<len;ii++){
while(nums[ii]!=ii){
if(nums[ii]==nums[nums[ii]]){
*duplication=nums[ii];
return true;
}
int temp=nums[ii];//保存将要交换的值,同时也保存了对应下标
nums[ii]=nums[temp];
nums[temp]=temp;
}
}
return false;
}
思路四:改进前一版不能输出第一次出现的重复字符
bool duplicate(int numbers[], int length, int* duplication) {
for(int i = 0;i < length; ++i){//这个方法妙在对于依次遍历过的每个数,都能在数组里记忆它出现过了。
//比如{2,2,1,0},第一次循环index = 2,a[2]=a[2] + 4 = 5,这样,a[2]=5 > 数组长度4,就说明2这个数字出现过了。
int index = numbers[i]%length;
if( numbers[index] >= length){
duplication[0] = index;
return true;
}
numbers[index] += length;
}
return false;
}
或
//题目里写了数组里数字的范围保证在0 ~ n-1 之间,所以可以利用现有数组设置标志,当一个数字被访问过后,可以设置对应位上的数 + n,之后再遇到相同的数时,会发现对应位上的数已经大于等于n了,那么直接返回这个数即可。
bool duplicate(int numbers[], int length, int* duplication) {
for (int i = 0; i < length; ++i) {
int index = numbers[i];
if (index >= length) index -= length;
if (numbers[index] >= length) {
duplication[0] = index;
return true;
}
numbers[index] += length;
}
return false;
}