文章目录
1.题目
简单 通过率:53.96% 时间限制:1秒 空间限制:256M
知识点
数组
描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1
数据范围:0\le n \le 10000 \0≤n≤10000
进阶:时间复杂度O(n)\O(n) ,空间复杂度O(n)\O(n)
示例1
输入:
[2,3,1,0,2,5,3]
复制
返回值:
2
复制
说明:
2或3都是对的
2.思路
- 思路一
由于HashSet的get方法是O(1)复杂度,优先考虑使用HashSet,当HashSet存在时说明重复。 - 思路二
用数组替代HashSet,因为题目给出的提交是数组元素都小于N(N是数组长度)。所以考虑再使用一个数组,当对应下标数字出现直接+1。 - 思路三
前两种方法有空间消耗,可以考虑原地排序,将数组放到对应的位置上,使用交换方法,如果坑位上有人,说明重复了。
3.实现
3.1 HashSet实现
public int duplicate(int[] numbers) {
// write code here
if(numbers == null || numbers.length == 0){
return -1;
}
HashSet<Integer> container = new HashSet<>();
for (int n : numbers) {
if (container.contains(n)) return n;
container.add(n);
}
return -1;
}
3.2 等长数组实现
public int duplicate(int[] numbers) {
// write code here
if(numbers == null || numbers.length == 0){
return -1;
}
int[] containers = new int[numbers.length];
for(int n:numbers){
containers[n] += 1;
if(containers[n]>1) return n;
}
return -1;
}
3.3 原地交换排序
public int duplicate(int[] numbers) {
// write code here
if(numbers == null || numbers.length == 0){
return -1;
}
for (int i = 0; i < numbers.length; i++) {
int a = numbers[i];
if(a!=i) {
if(numbers[a]==a) return a;
swap(a,i,numbers);
}
}
return -1;
}
public void swap(int a,int i,int[] numbers) {
int temp = numbers[a];
numbers[a] = numbers[i];
numbers[i] = temp;
}
总结
这是牛客网 剑指Offer JZ03题,考察的主要是数组等数据结构,属于简单类型。
剑指Offer 系列在github上有一个开源项目,主要是本系列博客的demo代码。https://github.com/forestnlp/alg
如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。
您的支持是对我最大的鼓励。