题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
算法
(基于交换)
相似题 LeetCode 41.第一个缺失的正数
- 遍历数组,把元素i放到下标为i的位置上,如果下标为i的位置上元素值不是i,那就把当前位置和下标为i的数进行交换,那么i就到了正确的位置,否则就继续往下遍历数组
- 再遍历一次数组,如果元素i和它的下标不相等,说明元素i就是重复的元素了,此题我们通过指针返回其中一个重复元素就可以了
核心代码
for (int i = 0; i < length; i ++) {
while(numbers[numbers[i]] != numbers[i]) {
swap(numbers[i], numbers[numbers[i]]);
}
}
详细解释
下标:0 1 2 3 4
数组:2 3 4 4 1
遍历数组
i = 0时
nums[0] = 2, 那2应该到下标为2的位置,所以和4交换
交换后:4 3 2 4 1
继续看换过来后nums[0] = 4是否在合适的位置,4应该到下标为4的位置,所以和1交换
交换后: 1 3 2 4 4
同理我们继续把1和3交换
交换后: 3 1 2 4 4
然后继续把3和4交换
交换后: 4 1 2 3 4
注意:此时nums[0] = 4,已经不需要放到下标为4的位置了,因为已经有个4放在那了
因此i = 0这种情况结束
i = 1时
继续上面的过程
...
...
时间复杂度是 ,空间复杂度是
C++代码
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) {
// Judge if the input is valid
for (int i = 0; i < length; i ++) {
if(numbers[i] < 0 || numbers[i] > length - 1) return false;
}
// Make the element in the right position
// Such as element 3 should in index 3
for (int i = 0; i < length; i ++) {
while(numbers[numbers[i]] != numbers[i]) swap(numbers[i], numbers[numbers[i]]);
}
// return a duplicate number by reference (point)
for (int i = 0; i < length; i ++) {
if (numbers[i] != i) {
*duplication = numbers[i];
return true;
}
}
}
};
其他方法:
- 排序:时间复杂度是 ,空间复杂度是
- 创建一个新数组:时间复杂度是 ,空间复杂度是
写在最后:我的博客主要是对计算机领域所学知识的总结、回顾和思考,把每篇博客写得通俗易懂是我的目标,分享技术和知识是一种快乐 ,非常欢迎大家和我一起交流学习,有任何问题都可以在评论区留言,也期待与您的深入交流(^∀^●)