數組中的重複數字和消失數字求解模板(下標哈希法)

由於數組中存的爲1~n,都爲正數,我們可以用正負號來表示下標爲 i 的數在數組中是否出現。搜索遍歷整個數組時,如果已經爲負數,那麼之前一定出現過一次,這個數就是我們要找的重複的數字。

最後哪些值爲正數的下標i所對應的數字i+1就是在數組中沒有出現過的數字。

切記:index=abs(nums[i])-1;取下標的時候一定要加絕對值!!原來的數可能已經添加了負號

442. 數組中重複的數據

代碼(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;
}

448. 找到所有數組中消失的數字

代碼(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;
}

面試題 17.19. 消失的兩個數字

這一題和上面不同的是數組長度不夠用,由於缺失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;
}

總結:

通過這種下標哈希法,我們用負號來表示當前下標的數字是否出現過,此法可以求任意重複或消失的數字。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章