2020秋招提前批开始了?莫慌,一定要把剑指offer多刷几遍。
题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
测试用例
给定数组{2,3,1,0,2,5,3}和数组长度7;
返回值true,并将第一个重复的数字2赋值给int *duplication。
解题方案
Solution1:哈希+遍历
根据值范围为0~n-1的特点,创建一个长度为n的bool类型哈希数组hash,初始化为false;从头遍历原始数组,将遍历到的数字的在hash数组中的值修改为true;遍历过程中遇到hash数组中已经为true的数字即为首个重复数字。
class Solution {
public:
//哈希+遍历
//判断一个数组中是否含有重复的数字
bool duplicate(int numbers[], int length, int* duplication) {
//创建一个下标为0~n-1的哈希数组,初始化为0,从头遍历,更新每个的计数,当遇到计数大于1的,返回true
vector<bool> hash(length, false);
for(int i=0; i<length; ++i){
if(hash[numbers[i]]){
*duplication = numbers[i];
return true;
}
else{
hash[numbers[i]] = true;
}
}
return false;
}
};
Solution2:in-place算法
参考自:牛客网官方题解
方法一中的一个条件我们没有用到。也就是数据的范围是0-n-1。所以我们可以这么做:
设置一个指针i指向开头0,对于arr[i]进行判断,
(1)如果arr[i] == i, 说明下标为i的数据正确的放在了该位置上,让i++;
(2)如果arr[i] != i, 说明没有正确放在位置上,那么我们就把arr[i]放在正确的位置上,也就是交换;
(3)arr[i] 和arr[arr[i]]。交换之后,如果arr[i] != i, 继续交换;
(4)如果交换的过程中,arr[i] == arr[arr[i]],说明遇到了重复值,返回即可。
//in-place算法
bool duplicate(int numbers[], int length, int* duplication) {
int temp;
for(int i=0; i<length; ++i){
//当i位置元素不是i时,将numbers[i]交换到numbers[numbers[i]]
while(numbers[i]!=i){
//在numbers[i]的位置已有该元素时,证明该数字重复
if(numbers[i]==numbers[numbers[i]]){
*duplication = numbers[i];
return true;
}
//swap(i, numbers[i]);
else{
temp = numbers[i];
numbers[i] = numbers[temp];
numbers[temp] = temp;
}
}
}
return false;
}
Solution3:in-place算法plus
参考自:牛客网评论区(ID:王大爷)
用原始一维数组来保存两种信息 怒赞!
不需要额外的数组或者hash表来保存,题目保证数组里数字的范围在0 ~ n-1之间,所以可以利用现有数组设置标志,当一个数字i被访问过后,可以设置对应位numbers[i]上的数 + length(因为该对应位+length可以通过%length得到原始值,故不需要担心数组元素被更改),之后再遇到相同的数时,会发现对应位上的数已经大于等于n了,那么直接返回这个数即可。
//只用原始一维数组来保存两种信息,tql,膜拜
bool duplicate(int numbers[], int length, int* duplication) {
for(int i=0;i!=length;++i){
//得到原始数组中numbers[i]位置的值
int index=numbers[i]%length;
//当numbers[index]>=length表示之前已经遍历过index这个数字,因此重复
if(numbers[index]>=length){
*duplication=index;
return true;
}
//遍历到的每个数字index,都在numbers[index]的位置+length
//既能表示index出现过,又不会丢失原始数组numbers[index]的信息(%length)
numbers[index]+=length;
}
return false;
}