数组中重复的数字

题目描述

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

解法一:

通过排序将数组排序,遍历数组便可以得到第一个重复的数字,快排的事件复杂度为O(nlogn)。

解法二:

可以通过Set、Map、数组等作为辅助空间,遍历输入序列时记录其出现的次数,第一个次数为2的便为所求的数字。(使用数组作为辅助空间时,由于序列中数字取值为0到n-1,所以可以使用a[i]记录i)。事件复杂度为O(n),空间复杂度为O(n)。

public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if(numbers == null || length == 0) {
            duplication[0] = -1;
            return false;
        }
        Set<Integer> set = new HashSet<Integer>();
        for(int i : numbers) {
            if(set.contains(i)) {
                duplication[0] = i;
                return true;
            }
            else
                set.add(i);
        }
        duplication[0] = -1;
        return false;
    }
}
解法三:

虽然该算法可以实现时间复杂度为O(n),空间复杂度为O(1)。但是只适合较小的数字,很容易产生溢出,因此极度不推荐,仅作为一种思路记录下来。
令m = numbers[i],将numbers[m]置为 m + length, 这样表示已经存在m,假设以后遍历到 n = numbers[j], 若此时numbers[n]已经被加了lenth,可以得到之前已经存在过了n,则n便是第一次重复的数字。

这种算法修改了输入数据,并且在+length的过程中很容易导致溢出。

public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if(numbers == null || length == 0) {
            duplication[0] = -1;
            return false;
        }
        for(int i = 0; i < length; i++) {
            int m = numbers[i];
            if(m >= length)
                m -= length;
            if(numbers[m] > length) {
                duplication[0] = m;
                return true;
            }
            numbers[m] += length;
        }
        duplication[0] = -1;
        return false;
    }
}

如果将题意修改为输出任意一个重复数字即可,不要求输出第一个重复数字。
由于输入序列中数字取值为0到n-1,若数组中没有重复数字,则numbers[i]中的值一定为i。
我们可以利用这一特性,从头遍历输入序列,将i放到numbers[i]上,若此时numbers[i]上早就存在了数字i,则i就是一个重复的数字。
即:
从头遍历输入 序列,令j = numbers[i]。
若j = i,则i++;
若j!= i, 则判断numbers[j] 是否等于j。若numbers[j] = j,则j即为一个重复的数字;
若numbers[j] != j,则交换numbers[i]与numbers[j]。继续判断当前i。

public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        int i = 0, j = 0;
        if(numbers == null || length == 0) {
            duplication[0] = -1;
            return false;
        }
        while(i < length) {
            if(numbers[i] != i) {
                j = numbers[i];
                if(numbers[j] == numbers[i]) {
                    duplication[0] = numbers[i];
                    return true;
                }
                else {
                    int tmp = numbers[i];
                    numbers[i] = numbers[j];
                    numbers[j] = tmp;
                }
            }
            else
                i++;
        }
        duplication[0] = -1;
        return false;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容