《剑指offer》c++版本 3.数组中重复的数字

如题:

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

方法由很多,四种,显然,排序法和哈希查找法都可以。第三种方法比较巧妙,利用了题目中数字都在0~n-1这个限制,第四种方法,也就是暴力遍历法,能解决问题,但不推荐。

方法1:排序法:使用快速排序,平均时间复杂度为O(nlogn),最坏O(n^2),需要修改原数组,和暴力遍历法相同,。

方法2:哈希查找法:将数组中元素依次加入hash表中,遇到重复的元素即可返回,时间复杂度为O(1),但需使用额外O(n)的空间。

方法3:方法三就比较巧妙了,这也是剑指推荐的方法,时间复杂度为O(n),剑指上很多题目,其实都是可以通过查找规律,找到更好的方法。这道题,数组长度为n,数字范围为0~n-1,显然,如果不重复,排好序后,每个元素都应该存在自己值对应的下标中。因此,我们遍历从0遍历数组,将遍历到的值,替换到其对应下标所在位置,如果已经存在,说明重复,返回即可。

方法4:暴力遍历法,只有在无路可走的情况下,方可出此下策,时间复杂度为O(n^2)。双重循环,对于每一个元素,遍历其后的数组,查找相同元素。

方法2,3是比较容易想到的,有经验的话,看到数字范围0~n-1也比较容易想到第三种,新手可能选择第四种。下面是c++语言的版本方法3。

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, val;
        
        //特殊情况处理
        if (length < 2)
            return false;
        *duplication = -1;
        
        //遍历数组
        for (i = 0; i < length;)
        {
            if (numbers[i] == i)
                i++;
            else if (numbers[i] == numbers[numbers[i]])
            {
                *duplication = numbers[i];
                return true;
            }
            else
            {
                val = numbers[numbers[i]];
                numbers[numbers[i]] = numbers[i];
                numbers[i] = val;
            }            
        }
        return false;
    }
};

=============================================================================================

Linux应用程序、内核、驱动,后台开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值