由於數組中存的爲1~n,都爲正數,我們可以用正負號來表示下標爲 i 的數在數組中是否出現。搜索遍歷整個數組時,如果已經爲負數,那麼之前一定出現過一次,這個數就是我們要找的重複的數字。
最後哪些值爲正數的下標i所對應的數字i+1就是在數組中沒有出現過的數字。
切記:index=abs(nums[i])-1;取下標的時候一定要加絕對值!!原來的數可能已經添加了負號
代碼(C語言)
int* findDuplicates(int* nums, int numsSize, int* returnSize){
int i,j,index;
int *rst=(int*)malloc(sizeof(int)*(numsSize+1));
*returnSize=0;
for(i=0;i<numsSize;i++){
index=abs(nums[i])-1;//記下數字num[i]在數組的下標
if(nums[index]<0){//小於0,那麼數字index+1之前出現過
rst[(*returnSize)++]=index+1;
}
nums[index]=-abs(nums[index]);//否則,用負號來表示數字index+1出現過
}
return rst;
}
代碼(C語言)
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize){
int i,index;
int *rst=(int*)malloc(sizeof(int)*(numsSize+1));
for(i=0;i<numsSize;i++){
index=abs(nums[i])-1;//下標
nums[index]=-abs(nums[index]);//將小標爲index的數字改爲負數,表示數字index+1出現過
}
*returnSize=0;
for(i=0;i<numsSize;i++){
if(nums[i]>0){//遍歷過後,數字爲負數,表示當前下標i所對應的數字i+1沒有出現過
rst[(*returnSize)++]=i+1;
}
}
return rst;
}
這一題和上面不同的是數組長度不夠用,由於缺失2個數字,因此額外增加兩個空間的長度。做法和上述一致!
代碼(C語言)
int* missingTwo(int* nums, int numsSize, int* returnSize){
int i,index;
//數組長度是少了兩個空間的,我們額外添加一個數組來存放這兩個數,下標分別爲numsSize和numsSize+1,0表示沒出現,-1表示出現
int* numsplus=(int*)malloc(sizeof(int)*2);
memset(numsplus,0,sizeof(numsplus));
for(i=0;i<numsSize;i++){
index=abs(nums[i])-1;
if(index<numsSize)
nums[index]=-abs(nums[index]);
else
numsplus[index-numsSize]=-1;
}
*returnSize=0;
for(i=0;i<2;i++){
if(numsplus[i]==0){
numsplus[(*returnSize)++]=numsSize+1+i;
}
}
for(i=0;i<numsSize;i++){
if(nums[i]>0){
numsplus[(*returnSize)++]=i+1;
}
}
return numsplus;
}
總結:
通過這種下標哈希法,我們用負號來表示當前下標的數字是否出現過,此法可以求任意重複或消失的數字。