剑指offer打卡Day12:数组中重复的数字

剑指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
    
  • 相关链接:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值