首页 > 试题广场 >

数组中重复的数字

[编程题]数组中重复的数字
  • 热度指数:535591 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
返回描述:
如果数组中有重复的数字,函数返回true,否则返回false。
如果数组中有重复的数字,把重复的数字放到参数duplication[0]中。(ps:duplication已经初始化,可以直接赋值使用。)
推荐
不需要额外的数组或者hash table来保存,题目里写了数组里数字的范围保证在0 ~ n-1 之间,所以可以利用现有数组设置标志,当一个数字被访问过后,可以设置对应位上的数 + n,之后再遇到相同的数时,会发现对应位上的数已经大于等于n了,那么直接返回这个数即可。

代码是C:

int find_dup( int numbers[], int length) {

    for ( int i= 0 ; i<length; i++) {

        int index = numbers[i];

        if (index >= length) {

            index -= length;

        }   

        if (numbers[index] >= length) {

            return index;

        }   

        numbers[index] = numbers[index] + length;

    }   

    return - 1

}


不需要额外的空间消耗,时间效率是O(n)
编辑于 2015-06-19 16:59:45 回复(97)
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if (numbers == null || length == 0) return false; 
        for (int i=0; i<length; ++i) {
            if (numbers[i] == i) continue; // 位置正确, 跳过
            if (numbers[i] != numbers[numbers[i]]) { // 如果数字和它应该去的位置上的数不一样就交换
                int tmp = numbers[i];
                numbers[i] = numbers[tmp];
                numbers[tmp] = tmp;
            } else {
                duplication[0] = numbers[i];
                return true;
            }
        }
        return false;
    }
编辑于 2021-02-05 14:38:48 回复(0)

思路

1.hash

很简单,遍历用hash保存和判断即可,不浪费口舌。

2.额外数组

由于数字在n->n-1范围,新建一个长度为n的数组来记录每个遍历的元素,检测到记录过的数字即为第一个重复数字。原理和hash其实没区别。

3.无额外空间(略复杂)

由于数字0->n-1,可将当前数字与数组中以该数字为坐标的数交换,如果发现以该数字为坐标的数等于当前数字,则重复。
eg:[2,1,3,1,4],
i=0时,将i=0和i=2交换->[3,1,2,1,4]
i=1,不变;
i=2,不变;
i=3,发现number[3](即1)与number[number[3]](即1)相同,即第一个重复数字。

代码

    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if (length <= 1) return false;
        for (int i = 0; i < numbers.length; i++) {
            if (i == numbers[i]) continue; // 删去也无所谓,能省一点不必要的计算
            if(numbers[i] == numbers[numbers[i]] && numbers[i] != i) {
                duplication[0] = numbers[i];
                return true;
            }
            swap(numbers, i, numbers[i]);
        }
        return false;
    }

    public static void swap(int[] arr, int a, int b) {
        arr[a] ^= arr[b];
        arr[b] ^= arr[a];
        arr[a] ^= arr[b];
    }
发表于 2021-01-27 15:58:48 回复(0)
请问大家这个为啥成功不了?
    public boolean duplicate(int numbers[],int length,int[] duplication) {
        if(numbers == null || length<=0){
            return false;
        }
        for(int i=0;i<numbers.length;i++){
            if(numbers[i] != i){
                if(numbers[i] != numbers[numbers[i]]){
                    //交换
                    int temp = numbers[i];
                    numbers[i] = numbers[temp];
                    numbers[temp] = temp;
                }
                duplication[0] = numbers[i];
                return true;//出现重复数字
            }
        }
        return false;
    }


发表于 2020-12-28 22:50:43 回复(0)
import java.util.HashSet;
public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
    if(numbers==null || numbers.length==0){
        return false;
    }
        boolean flag=false;
        int a=0;
        for(int i=0;i<numbers.length;i++){
            for(int j=i+1;j<numbers.length;j++){
                if(numbers[i]==numbers[j]){
                    flag=true;
                    a=numbers[i];
                    break;
                }
            }
            if(flag){
                break;
            }
        }
        if(flag){
            duplication[0]=a;
            return flag;
        }
        return flag;
    }
}

发表于 2020-11-25 14:59:57 回复(0)
看题目中的第一句话“在一个长度为n的数组里的所有数字都在0到n-1的范围内。”                   第一时间就想到了计数排序的原理。
public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        int[] temp = new int[length];
        for(int i=0;i<length;i++){
            temp[numbers[i]]++;
        }
        for(int i=0;i<length;i++){
            if(temp[numbers[i]]>1){
                duplication[0] = numbers[i];
                return true;
            }
        }
        return false;
    }
}



发表于 2020-11-17 17:41:49 回复(0)
import java.util.*;
public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        return solution2(numbers, length, duplication);
    }
    
    private boolean solution1(int numbers[],int length,int [] duplication) {
        if (length == 0) {
            return false;
        }
        Set<Integer> set = new HashSet<>();
        for (int i : numbers) {
            boolean b = set.add(i);
            if (!b) {
                duplication[0] = i;
                return true;
            }
        }
        return false;
    }
    private boolean solution2(int numbers[], int length, int[] duplication) {
        if (length == 0) {
            return false;
        }
        for (int i = 0; i < numbers.length; i++) {
            int index = numbers[i];
            if (index >= length) {
                index -= length;
            }
            numbers[index] += length;
            if (numbers[index] > 2 * length) {
                duplication[0] = index;
                return true;
            }
        }
        return false;
    }
}
发表于 2020-10-28 13:47:50 回复(0)
// 解法一:使用hash表(hashmap),遍历数组找到重复的数字即返回true。时间复杂度O(n),空间复杂度O(n)
// 略
// 解法二:利用题目的特性,重复数字不指定,值范围在0~n-1。时间复杂度O(n),空间复杂度O(1)


 
 public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if (numbers == null || numbers.length <= 0) {
            return false;
        }
        // 验证输入数组值是否正确
        for (int i = 0; i< length ; i++) {
            if (numbers[i] > length - 1 || numbers[i] < 0) {
                return false;
            }
        }
        // 将下标未i对应的数字m移到m位置上
        for (int i = 0; i < numbers.length; i++) {
            if (numbers[i] == i ) {
                continue;
            }
            // 要一直循环,知道找到下标和值相同的位置
            while(numbers[i] != i) {
                if (numbers[i] == numbers[numbers[i]]) {
                    duplication[i] = numbers[i];
                    return true;
                }
                int temp = numbers[numbers[i]];
                numbers[numbers[i]] = numbers[i];
                numbers[i] = temp;
            }
        }
        return false;
    }
}

编辑于 2020-10-13 22:13:48 回复(0)
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if (length <= 0) {
            return false;
        }
        // 因为数组里的所有数字都在0到n-1的范围内
        int count[] = new int[length];
//        Arrays.fill(count, 0);, int 的默认值就是 0
        int a;
        for (int i = 0; i < length; i++) {
            a = numbers[i];
            count[a] ++;
            if (count[a] == 2) {
                // 这个数字前面已经出现过一次,现在出现第二次记录到 duplication 数组中
                // PS : length of duplication array is 1
                duplication[0] = a;
                return true;
            }
            // 该数字已经出现多次(count[a] > 2), 不需要做过多的其他处理
        }
        return false;
    }

发表于 2020-10-03 11:21:54 回复(0)
set集合具有数据不能重复的特点,在逐个添加数据的过程中,判断set集合size的变化,遇到不变的时候就是重复数据点。
发表于 2020-09-15 12:19:13 回复(0)
public boolean duplicate(int numbers[],int length,int [] duplication) {
        if(length<=0&&numbers==null)   return false;
        for(int i=0;i<length;i++){
            if(numbers[i]!=i){
                while(numbers[i]==numbers[numbers[i]]){
                    duplication[0]=numbers[i];
                    return true;
                }
                swap(numbers,i,numbers[i]);
            }
        }
        return false;
    }
    private void swap(int numbers[],int i,int j){
        int t = numbers[i];
        numbers[i]=numbers[j];
        numbers[j]=t;
    }

主要有两个动作,一个前提是index和自己的值相比,在这个基础上比较交换的值和交换值为index的值相比
如果不相等则交换后与自身比较,相等则赋值后返回

发表于 2020-08-26 15:52:31 回复(0)
LinkedHashMap使用:两次遍历,保证顺序
import java.util.*;
public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if (length <= 0 || numbers == null) return false;
        Map<Integer,Integer> map = new LinkedHashMap<>(16);
        for (int i = 0; i < length; i++) {
            if (!map.containsKey(numbers[i])) map.put(numbers[i],1);
            else map.put(numbers[i],map.get(numbers[i])+1);
        }
        for (Map.Entry<Integer,Integer> entry : map.entrySet()) {
            if (entry.getValue() > 1) {
                duplication[0] = entry.getKey();
                return true;
            }
        }
        return false;
    }
}


发表于 2020-08-22 11:16:14 回复(0)
public static int getNumber(int[] ints){
        //定义一个与数组长度相同的boolean数组
        boolean[] booleans = new boolean[ints.length];
        //遍历数组中的每个数,将遍历的数作为boolean的索引
        for (int i = 0; i < ints.length; i++) {
            //判断boolean索引的元素是否是fales,如果是则更改为true,反之直接返回当前的索引,即为重复的数字。
            if (booleans[ints[i]] != true){
                booleans[ints[i]] = true;
            }else {
                return ints[i];
            }
        }
        return -1;
    }

发表于 2020-07-10 14:40:43 回复(0)
/*
须注意到数组中值的范围。
关键是加上length后,也能得到数组原来存储的数值。,只需要减掉一个length即可。
*/
public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        for (int i=0;i<length;i++) {
            int num = numbers[i];
            if (num >= length) {
                num -= length;
            }
            if (numbers[num] >= length) {
                duplication[0] = num;
                return true;
            } else {
                numbers[num] += length;
            }
        }
        return false;
    }
}

/*

*/

    public boolean duplicate(int numbers[],int length,int [] duplication) {
        HashSet<Integer> set = new HashSet<Integer>();
        for (int i=0;i<length;i++) {
            if (!set.add(numbers[i])) {
                duplication[0] = numbers[i];
                return true;
            }
        }
        return false;
    }

编辑于 2020-07-08 16:27:14 回复(0)
bitMap 一个数字占一bit
flag=0 
判断是否重复:flag右移number位,查看最右位是否为1,为1则有重复
否则当前number占flag中的第number位为1
public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        //bitMap 一个数字占一bit
        //flag>>number &1==1重复
        //flag|=1<<number
        int flag=0;
        if(length==1){
            return false;
        }
        int k=0;
        for(int i=0;i<length;i++){
            if(((flag>>numbers[i])&1)==1){//重复
                duplication[k++]=numbers[i];
                break;
            }
            else flag|=1<<numbers[i];//占位
        }
        return k!=0;
    }
}

发表于 2020-07-08 02:52:43 回复(0)
public class Solution {
//搬照扑克牌顺子的那个判断是否重复的思路
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        int flag = 0;
        boolean first = true;
        int i = 0;
        for( i =0;i<length;i++){
            if(first==true){
                first = false;
                flag |= 1<<numbers[i];
                
            }
            else{
                  
                 if(((flag >> numbers[i]) & 1) == 1){
                    duplication[0] = numbers[i];   
                     break;
            }
                flag |= 1<<numbers[i];           
            }             
        }
        if(i == length) return false;
        return true;
        
    }
}
发表于 2020-07-06 10:38:28 回复(0)
利用set来做,就非常简单了
public boolean duplicate(int numbers[],int length,int [] duplication) {
    if(numbers == null || length <= 0)    return false;
    HashSet<Integer> set = new HashSet<>();
    for(int i = 0; i < length; i++){
        //如果set里面已经存在当前值了,就直接赋值给duplication[0]
        if(!set.add(numbers[i])){
            duplication[0] = numbers[i];
            return true;
        }
    }
    return false;
}


发表于 2020-07-04 16:23:06 回复(0)
import java.util.*;
public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if (length==0){
            return false;
        }
        Arrays.sort(numbers);
        for(int i=0;i<length-1;i++){
            if(numbers[i]==numbers[i+1]){
                duplication[0]=numbers[i];
                return true;
            }
        }
        return false;
    }
}

发表于 2020-06-27 16:59:36 回复(0)
剑指offer里面的思路 时间复杂度O(n),空间复杂度O(1);

 public boolean duplicate(int numbers[],int length,int [] duplication) 
    {
        if(numbers==null) return false;
    for(int i=0;i<numbers.length;++i)
    {
        if(numbers[i]!=i)
        {
            if(numbers[i]==numbers[numbers[i]])
            {
                duplication[0]=numbers[i];
                return true;
            }
              int temp=numbers[i];
              numbers[i]=numbers[temp];
              numbers[temp]=temp;
        }
          
    }   
        return false;
    }


     
发表于 2020-06-19 20:58:23 回复(0)
import java.util.Arrays;

public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if(length > 0)
            Arrays.sort(numbers);
        int n = -1;
        for(int i = 0; i < length;i++){
            if((i + numbers[0]) != numbers[i]){
                n = numbers[i];
                break;
            }
        }
        duplication[0] = n;
        if(n != -1){
            return true;
        }
        return false;
    }
}

发表于 2020-06-18 23:05:10 回复(0)