50.数组中重复的数字

题目描述

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


思路一:采用辅助数组arr,对已出现的数进行标记;时间复杂度、空间复杂度均为O(N)。


代码一:

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 || numbers == NULL)
            return false;
        vector<bool> arr(length, false);  //用bool数组作为标志数组,比用int数组更节省空间
        for(int i = 0; i < length; ++i) {
            if(arr[numbers[i]]) {
                *duplication = numbers[i];
                return true;
            } else {
                arr[numbers[i]] = true;
            }
        }
        return false;
    }
};

思路二:由于题目没有要求需要保存原有数组不变,且数组内的数均小于n,因此可以在访问一个数后,将以该数为索引下标的数加上n;继续往后循环,若索引值大于n,则减n即为真实索引值;再以索引值作为下标取数,若该数大于n则表示之前已经出现过,此时返回索引值即可。 不需要额外的空间消耗,时间效率是O(n)

代码二:

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 || numbers == NULL) {
            return false;
        }
        int idx;
        for(int i = 0; i < length; ++i) {
            idx = numbers[i];
            if(idx >= length) {
                idx -= length;
            }
            if(numbers[idx] >= length) {
                *duplication = idx;
                return true;
            } else {
                numbers[idx] += length;
            }
        }
        return false;
    }
};


思路三:对数组进行重新排序,满足numbers[i]=i;从i=0开始循环,直到第一次出现需要交换的位置处已排好,即出现重复数,此时返回索引值即可,时间复杂度同样为O(N),空间复杂度为O(1)。


代码三:

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
    void swape(int* i, int* j) {
        int tmp = *i;
        *i = *j;
        *j = tmp;
    }
    bool duplicate(int numbers[], int length, int* duplication) {
        if(length <= 0 || numbers == NULL) //数组为空、数组长度非正,返回false
            return false;
        for(int i = 0; i < length; ++i) { //数组内的数不在【0, n-1】范围内,返回false
            if(numbers[i] < 0 || numbers[i] >= length)
                return false;
        }
        int idx;
        for(int i = 0; i < length; ++i) {
            while(numbers[i] != i) {  //确保当前下标i的索引值与i相等
                idx = numbers[i];
                if(numbers[idx] == idx) { //若索引值作为下标,对应地方满足上述要求,说明已找到重复数字
                    *duplication = idx;
                    return true;
                } else {  //若索引值作为下标,对应处不满足要求,则对这两个数进行交换
                    swape(&numbers[i], &numbers[idx]);
                }
            }
        }
        return false;
    }
};

猜你喜欢

转载自blog.csdn.net/nichchen/article/details/80418166