数组中的重复数字

数组中的重复数字

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

剑指offer

第一种

如书上说的对数组进行排序然后遍历。

    public static void main(String[] args) {
        int [] array={2,3,1,0,2,5,3};
        quickSort(array,0,array.length-1);
        //打印
        for(int i:array){
            System.out.println(i);
         }

    Map<Integer,Integer> map=new HashMap<>();
    for(int i=1;i<array.length;i++){
       if(array[i]==array[i-1]){
           int temp=array[i-1];
           int index=i-1;
           while(array[i]==temp&&i<array.length){
               i++;
           }

           map.put(temp,i-index);
       }
    }

    map.forEach((key, value) -> {
        System.out.println(key + " : " + value);
    });
}

public static void quickSort(int [] array,int start,int end){
    if(array.length==0|| array==null)
        return;
    if(start<end) {
        //枢轴点
        int pivot = findPivot(array, start, end);
        quickSort(array, start, pivot - 1);
        quickSort(array, pivot + 1, end);
    }
}

//查找枢轴点
public static int findPivot(int [] array,int start,int end){
    int temp=array[start];
    while(start<end){
        //从后往前
        while(end>start&&array[end]>=temp){
            end--;
        }
        if(start<end){
            array[start]=array[end];
        }
        //从前往后
        while(start<end&&array[start]<=temp){
            start++;
        }
        if(start<end){
            array[end]=array[start];
        }
    }
    array[start]=temp;
    return  start;
}

`
结果:

时间复杂度主要是在排序上 O(nlogn)


第二种

使用hash 表

`

public static void main(String[] args) {
    int [] data={2,3,1,0,2,5,3};
    HashMap<Integer,Integer> map=new HashMap<>();
    for(int i=0;i<data.length;i++){
        if(map.containsKey(data[i])){
            map.put(data[i],map.get(data[i])+1);
        }else
            map.put(data[i],1);
    }
    map.forEach((key,value)->{
        if(value>1)
            System.out.println(key+" : "+value);
    });
}

`

结果:

分析 时间复杂度是O(n),空间复杂度O(n)

第三种

我感觉用自己的语言解释不清晰。

看题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。

思路:创建长度为n的数组,将数组的值存到与该值相等的指标数组下(我说的不好还是举个例子:如 data[3]=2,判断下data[2]的值是不是等于2 。如果是就说明重复了)

{2,3,1,0,2,5,3}

开始:

data[0]=2 不等于0 与 data[2]=1互换

结果:{1,3,2,0,2,5,3}

data[0]=1 不等于0 与 data[1]=3 互换

结果:{3,1,2,0,2,5,3}

data[0]=3 不等于0 与 data[3]=0 互换

结果:{0,1,2,3,2,5,3}

然后判断 data[0]=0 等于0 data[1]=1 等于1 …一直到data[4]=2
与4 不相等 看data[2]=2 与2相等 说明重复了

public static void main(String[] args) {
    int [] data={2,3,1,0,2,4,4,5,4,4,3,1,2,3};
    //map用来统计个数
    Map<Integer,Integer> map=new HashMap<>();

    for(int i=0;i<data.length;i++){
        //因为要统计个数我加了个条件和书上不太一样
        //data[i]!=-1
        while(data[i]!=i&&data[i]!=-1) {
            //说明重复
            if (data[data[i]] == data[i]) {
                if (map.containsKey(data[i])) {
                    map.put(data[i], map.get(data[i])+1);
                } else {
                    map.put(data[i], 2);
                }
                //因为改位置上的值为重复值,将他置为-1是为了统计重复数字出现次数
                data[i] = -1;
                break;
            } else {
                int temp = data[i];
                data[i] = data[data[i]];
                data[temp] = temp;
            }
        }
    }
    map.forEach((key,value)->{
        System.out.println(key+" : " +value );
    });
}

`

结果:

为什么要将data[i]置为-1? 是为了方便统计个数

如:{0,1,2,3,2,4} 当下标为4 即指向 2时判断2为重复数字,然后计算数组2出现次数为2,当下标移到5是即指向4,换位后{0,1,2,3,4,2},这时是不是又会多判一次2 这样2的出现次数是3了 所以错了。

这个算法时间复杂度O(n),空间复杂度比用hash表小。


说明:

剑指offer上没有说统计次数,这个是我自己加上去的要求。


会想起阿里面试官问我的问题 其实和这个有点像统计两个集合中的相同的元素?两个集合的元素都是0——n之间? 用最最优的方法统计?

那时候我说了hash 表,他好像不是很满意,现在思路就是就是讲两个集合合并成一个数组 用方法3就可以了。 加油加油!

慢慢积累吧加油加油!

猜你喜欢

转载自blog.csdn.net/u013164931/article/details/79741700