剑指offer打卡Day12:数组中重复的数字
题1:数组中重复的数字
题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。
数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中第一个重复的数字。
例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
返回描述:
如果数组中有重复的数字,函数返回true,否则返回false。
如果数组中有重复的数字,把重复的数字放到参数duplication[0]中。(ps:duplication已经初始化,可以直接赋值使用。)
解析 & 解答:
-
吐槽下这题:当看到题目给的返回值是Boolean时候,其实是有点懵的,不是要返回重复值吗,咋就直接true/false了?
然后轻敌了,上来直接哐哐用数组一顿操作:
//直接用数组计数,然后用输出任意一个重复的数字 public boolean duplicate(int numbers[],int length,int [] duplication) { int con[] = new int[length]; for(int i = 0;i < length ; i++){ con[numbers[i]]++; } for(int i = 0;i < length ; i++){ if(con[i] > 1){ duplication[0] = i; return true; } } return false; }
结果:
然后到这才发现需要输出 首次重复的数字,而不是任意重复的数字好吧继续开整。
-
稍作优化:
//直接用一次遍历即可,找出第一位重复的数字 public boolean duplicate_me(int numbers[], int length, int[] duplication) { if (length <= 0) { return false; } if(numbers==null||numbers.length==0){ return false; } int con[] = new int[length]; for (int i = 0; i < length; i++) { con[numbers[i]]++; //累加后直接对所在元素进行判断,大于1则为重复 if (con[numbers[i]] > 1) { duplication[0] = numbers[i]; System.out.println(i); return true; } } return false; }
-
不过总是用一种方法解题
有点枯燥是无法让人进步的,这时我看了下牛客网中Java解答的代码,发现可以用Set这种数据结构辅助完成public boolean duplicate(int numbers[],int length,int [] duplication) { if(numbers==null||numbers.length==0){ return false; } Set<Integer> set = new HashSet<>(); //用set这种无法储存重复元素的集合,也是可以完成题目的意思 for (int i = 0; i < numbers.length; i++) { if (set.contains(numbers[i])){ duplication[0]=numbers[i]; return true; }else { set.add(numbers[i]); } } if (set.size()==length){ return false; } return true; }
补充:
-
对于Array 数组 与 Collection 集合的关系:
-
俗话说得好:
世界本没有集合,数组不够用了才有了集合
-
因为集合是对数组做的封装,数组永远比任何一个集合要快
-
同时也可以看到集合
AbstractCollection<E> :public Object[] toArray()方法
-
-
有人想有可以自动扩展的数组,所以有了List
- 同时又想要方便查找的,所以有了ArrayList
- 光查找不行啊,得方便增删改,所以有了LinkedList
- 感觉上面两个不够同步,不安全,然后又有了Vector
-
有的人想有没有重复的数组,所以有了Set
- 用Hash表来实现的 HashSet
- 实现了还不够啊,要自动排序才更方便,于是有了TreeSet
-
-
List方法与set方法的区别
(1)重复对象
list方法可以允许重复的对象,而set方法不允许重复对象
(2)null元素
list可以插入多个null元素,而set只允许插入一个null元素
(3)容器是否有序
list是一个有序的容器,保持了每个元素的插入顺序。即输出顺序就是输入顺序,而set方法是无序容器,无法保证每个元素的存储顺序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序
-
List 、Set、 Map关系
Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set |-HashSet └TreeSet Map ├Hashtable ├HashMap └WeakHashMap
-
相关链接:
-
其实博客只是辅助,最好还是自己看源码,比啥都清楚。
所以,刷题结束就去看源码吧。为了更好的下家哈哈。