【剑指offer】50:数组中重复的数字

题目描述:

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任一一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1
解题思路:

由于题目中告诉我们所有的数字都在0到n-1的范围内,因此如果没有重复,那么所存储的值也正好是0到n-1这n个数字,我们把原数组重新排列为一个元素和对应下标值相同的数组。

具体思路如下:从头到尾扫描整个数组中的数字,当扫描到下标为i的数字时,首先比较这个数字是不是等于下标i(数组存放原则:numbers[i] == i)。如果是,接着比较下一个数字;如果不是,则将其与第i个数字比较,若与第i个数字相同,则说明它就是一个重复数字,如果不同,就将其与第i个数字进行交换,也就是把它放到自己应在的位置去。重复这个过程,直到该位置上的数与下标相同为止。

例如:
    例如[2,3,1,0,2]
    遍历0位元素2:(交换0位元素2和2位元素1)->[1,3,2,0,2]
    遍历0位元素1:(交换0位元素1和1位元素3)->[3,1,2,0,2]
    遍历0位元素3:(交换0位元素3和3位元素0)->[0,1,2,3,2]
    依次遍历0、1、2、3位置元素,都符合存放原则numbers[i] = i,不做任何操作
    遍历末位元素2,此时末位元素2和2位元素2相等,出现了两次,即数字2位重复元素

代码实现:

(C语言)

int duplicate(int* numbers, int numbersLen ) {
    // write code here
    if (numbersLen <= 1) {
        return -1;
    }
    for (int i = 0; i < numbersLen; i++) {
        if (numbers[i] != i) {
            if (numbers[i] == numbers[numbers[i]]) {
                return numbers[i];
            }else {
                int temp = numbers[numbers[i]];
                numbers[numbers[i]] = numbers[i];
                numbers[i] = temp;
            }
            i--;   //遍历完0位元素以及交换完数字后,如果0位元素仍不符合数组存放原则:numbers[i] = i,那么还要重新遍历0位元素
        }
    }
    return -1;

 

posted @ 2021-07-11 20:46  zhang十六  阅读(43)  评论(0)    收藏  举报