数组中的重复数字和消失数字求解模板(下标哈希法)

由于数组中存的为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;
}

总结:

通过这种下标哈希法,我们用负号来表示当前下标的数字是否出现过,此法可以求任意重复或消失的数字。

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