剑指offer——面试题51:数组中重复的数字

来源:互联网 发布:Mac怎么改变照片日期 编辑:程序博客网 时间:2024/06/05 21:57

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

      代码:

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 <= 0)  // 注意,最好是 << 0,而不是 << 1.还有一种情况,numbers == NULL 注意补上            return false;        int num[255] = {0};   // 数组里面必须给定一个确定值,给length 是不行的        int count = 0;        for(int i = 0;i< length;++i)        {            if(numbers[i] >= length || numbers[i] < 0)                return false;        }        for(int i = 0;i< length;++i)        {            num[numbers[i]]++;        }        for(int i = 0;i< length;++i)        {             if(num[numbers[i]] > 1)  // 某个数字出现两次及以上            {                duplication[count++] =  numbers[i];               return true;                 break;  // break 一定放在 return true 后面。没有这个break也是可以的,那么,该循环就把所有的重复数字记录下来了。时间复杂度会高一点            }        }        return false ; // 正常情况下,默认返回 false 。只有当出现重复数字时,才返回 true    }};

      分析:上面我的解法,就是《剑指offer》书上 P261 提到的既不简单也不困难的解法,时间复杂度为 O(n)。这种方法是利用哈希表来解决。

      《剑指offer》 上提供了这样的解决思路:

      注意到,题目要求是数组中的数字都在 0~n-1 范围之内,如果这个数组没有重复的数字,那么,将数组排序之后,数字 i 将出现在下标为 i 的位置。由于数组中有重复的数字,所以,有些位置可能存在多个数字,有些位置可能没有数字。

      现在,让我们重新排这个数组。从头到尾依次扫描这个数组的数字。当扫描到下标为 i 的数字时,首先比较这个数字(记为 m )是不是等于 i ,如果是,接着扫描下一个数字。如果不是,在拿它和第 m 个数字进行比较。如果它和第 m 个数字相等,就代表找到了一个重复的数字,该数字就在下标 i 和下标 m 的位置都出现了。如果它和第 m 个数字不相等,就把第 i 个数字和第 m 个数字进行交换,把 m 放到属于它的位置。接下来,再重复地进行比较,交换的过程,直到我们发现一个重复的数字。

  但是我觉得这个方法并不好,太凑巧了,还是上面那个 哈希表的方法更通用些

代码:

bool duplicate(int numbers[], int length, int* duplication) {        if(length <= 1 || numbers == NULL)            return false;        for(int i = 0;i< length;++i)        {            if(numbers[i] >= length || numbers[i] < 0)                return false;        }        for(int i = 0;i < length;++i)        {            while(numbers[i] != i)            {                if(numbers[i] == numbers[numbers[i]])                {                    *duplication = numbers[i];                    return true;                }                int temp = numbers[i];                numbers[i] = numbers[temp];                numbers[temp] = temp;            }        }        return false ; // 正常情况下,默认返回 false 。只有当出现重复数字时,才返回 true    }


原创粉丝点击