【剑指Offer】面试题51:数字中重复的数字

一题目描述:

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

二:解题思路

第一种:排序

第二种:借助辅助空间,哈希的思想

借助辅助空间,hash,如果不需要保证原始numbers数字出现的先后顺序,则借助O(n)辅助空间
如果要保证原始顺序,则需要借助O(2n)辅助空间

 输入的数组有效且有重复的数字,则返回true
 否则,返回false


 输出重复的数字,是否要保持他在数组中出现的先后顺序,这个要注意
利用一个[长度][2]二维数组,下标表示0--n-1的n个数,第一列表示第一次出现的位置,第二列表示该数字是否重复
 遍历number数组,如果hash[number[i]][1]==0,则number[i]是重复的数,同时保证i与第一次出现的位置相同,防止后面出现重复数字,保存重复


第三种:交换的思想

0~n-1正常的排序应该是A[i]=i;因此可以通过交换的方式,将它们都各自放回属于自己的位置;

当扫描下标为i的数字时,首先比较这个数字的(m)是不是等于i,
如果是,接着扫描下一个数字
如果不是,将他与第m个数字比较,如果相等,就找到第一个重复的数字(第i个位置的数字与m位置的数字重复)
 如果与第m个位置的数字不相等,就将i--m位置的数字互换,把m放到属于它的位置上,接下来重复比较,交换的过程

三:代码实现

class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    bool duplicate(int numbers[], int length, int* duplication) {
     
        
        if(length<=1)  //如果只包含0,不合法,包含一个数字,不会重复
            return false;
        
        int hash[length][2];  //下标代表0--length
        memset(hash,-1,sizeof(hash));  //第一列存放数字第一次出现的位置  第二列存放是否重复
        //hash初始化-2;  第一个参数是指针或者数组,
        //第二个参数是要对该数组初始化的值,第三个参数是整个数组的大小,(注意不是数组的长度)
        //strlen返回的字符串的长度   数组的长度 sizeof(a)/sizeof(a[0])
        int i;
        for(i=0;i<length;i++)  
        {
            if(hash[numbers[i]][0]==-1)
                hash[numbers[i]][0]=i;  //第一次出现的地址
            else if(hash[numbers[i]][0]>=0)  //之前写成if 是不对的,上面刚刚出现一次,将-1-->0,下面就判断她重复出现了
                hash[numbers[i]][1]=0;  //第二次出现,0代表该数重复出现
        }
        int numOfDuplication=0;
        for(i=0;i<length;i++)
        {
            if(hash[numbers[i]][1]==0 && i==hash[numbers[i]][0]){//重复出现,且只保存第一次出现的,后面重复出现的不保存
                *duplication=numbers[i];
                numOfDuplication++;
                duplication++;
            }
        }
        if(numOfDuplication==0)  //无重复
            return false;
        else
            return true;
           }
};



class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    bool duplicate(int numbers[], int length, int* duplication) {
        int i;
        
        if(length<=1)
            return false;
        for(i=0;i<length;i++)
            if(numbers[i]<0 || numbers[i]>length-1)
                return false;
        int numOfDumplication=0;
        for(i=0;i<length;i++){
            while(i!=numbers[i]){
                if(numbers[i]==numbers[numbers[i]]){
                    *duplication =numbers[i];
                    duplication++;
                    numOfDumplication++;
                    i++; //遍历下一位
                    
                }//发现重复项
                else{
                    int temp=numbers[i];
                    numbers[i]=numbers[temp];
                    numbers[temp]=temp;
                }
            }
        }
        if(numOfDumplication==0)
            return false;
        else
            return true;
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值