剑指Offer-50.数组中重复的数字(C++/Java)

java

题目:

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

分析:

因为所有数字都在0到n-1的范围内,我们可以创建一个大小为n的数组v,每遍历一个数字,就将v[numbers[i]]标记为已访问过,每访问一个新的数字,就判断v中是否已经访问这个数字了,这样可以找到第一个重复的数字。

看了一下书中的答案,是通过遍历数组,将当前的数字和当前数字索引下的数字进行比较,如果不同就交换,直到访问的数字和该数字索引下的数字相等(不和当前的索引相同),便是第一个重复数字,如果将数组都遍历一遍了的话,就意味着没有重复数字。

以[1,3,2,0,2,5,3]举例

首先,遍历到数字1,数字1不等于当前索引0,且和numbers[1]也不相同,所以根numbers[1]的数字交换,当前数组为[3,1,2,0,2,5,3]。

由于3还是不等于0,再根numbers[3]交换,当前数组为[0,1,2,3,2,5,3].

由于0和当前索引0相同,扫描下一个数字,1和索引1相等,以此类推,直到扫描到numbers[4],也就是2,此时2不等于当前索引4,比较numbers[2]的数字恰好等于2,意味着这个元素是访问过的,这样便找到了第一个相同的元素。

还有一个比较巧妙的方法也是利用原数组,每访问一个元素,就将该元素作为索引指向的那个位置的元素进行标记,由于所有数字都在0到n-1的范围内,我们就将该数字作为索引指向的元素加上n,也就是如果访问到的元素是大于等于n的,意味着该索引数字,是我们当前访问过的,可以判断重复,要取当前数字的话只要减去n就可以了。

还是拿[1,3,2,0,2,5,3]举例

访问1,我们发现numbers[1]下的3小于n(7),意味着没有访问过,现在将1标记为访问,也就是将numbers[1]加上n,此时的数组为[1,10,2,0,2,5,3]

接下来访问下一个元素,但此时numbers[1]是10,大于7,意味着索引1代表的数字我们访问过了,要将numbers[1]的元素还原,减去7等于3,继续修改numbers[3]的元素为7,此时数组为[1,10,2,7,2,5,3]。

同理访问numbers[2]时,数组会变为[1,10,9,7,2,5,3]

访问numbers[3]时,数组会变为[8,10,9,7,2,5,3]

当我们访问numbers[4]时,也就是2这个数字时,此时numbers[2] > n(7),意味着2这个数字我们时访问过的!所以也就找到了第一个重复的数字。总结一下就是利用元素加上n来表示当前索引时我们访问过的,因为所有数字都在0到n-1的范围内,这个方法很巧妙。

程序:

C++

//use map

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)

return false;

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

if(m[numbers[i]] == 1){

*duplication = numbers[i];

return true;

}

else{

m[numbers[i]]++;

}

}

return false;

}

private:

map<int, int> m;

};

Java

//space O(1) time O(n)

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 || length == 0)

return false;

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

int index = numbers[i];

if(index >= length)

index -= length;

if(numbers[index] >= length){

duplication[0] = index;

return true;

}

numbers[index] += length;

}

return false;

}

}

以上是 剑指Offer-50.数组中重复的数字(C++/Java) 的全部内容, 来源链接: utcz.com/z/390054.html

回到顶部