用Java实现求一个数组中的出现次数最多的元素的个数

来源:互联网 发布:日程软件 知乎 电脑 编辑:程序博客网 时间:2024/06/03 11:16

前些天做笔试题的时候,遇到这一道题:用Java实现求一个数组中的出现次数最多的元素的个数。但是时间比较紧,我想出了先排序,然后遍历一遍,相邻元素相等则累计,不同则重新累计,遍历完就可以得到相同元素出现最多的元素。自认为还可以,不过面试官笑着对我说:“加入数组的元素不能排序呢?”。哦,我把数组默认当做int数组了,假如数组是String类型的或者是其他的类型,就不能使用我这种方式了。

其实很容易想到一种方法,就是将相同的元素先各就各位,比如装在一个集合中,最后清点下哪个集合最大就可以了。为了使不同的类型数据可以复用,使用泛型(不过如果是基本类型数组就要转化为包装类型了):

/**     * 使用ArrayList处理,如果是自己定义的类,则要合理重写equals方法     * @param a     * @return     */    public static <T> int getMostFrequentByArrayList(T a[]){        if(a == null||a.length == 0){            return 0;        }        int size  = a.length;        int result = 0;        //持有所有集合的集合。指定容量以免扩容带来的性能消耗,不过可能浪费空间        ArrayList<ArrayList<T>> severalTempList = new ArrayList<ArrayList<T>>(size);        for (int i = 0; i < size; i++) {            boolean isAdd = false;            T t = a[i];            //遍历severalTempList每个ArrayList,找到t所属的则添加上去            for(int j = 0;j < severalTempList.size();j++){                ArrayList<T> singleTemps = severalTempList.get(j);                if(singleTemps != null){                    if(t.equals(singleTemps.get(0))){                        singleTemps.add(t);                        isAdd = true;                    }                }            }            //找不到t所属的则创建新的ArrayList添加到severalTempList,并将t添加到新的ArrayList            if(!isAdd){                ArrayList<T> singleTemps = new ArrayList<T>();                singleTemps.add(t);                severalTempList.add(singleTemps);            }        }        //经过拆分后长度最大的集合        ArrayList<T> largestList = severalTempList.get(0);        //从索引为1开始就可以了        for(int i = 1;i < severalTempList.size();i++){            //通过遍历找到元素最多的集合            if(severalTempList.get(i).size() > largestList.size()){                largestList = severalTempList.get(i);            }            result = largestList.size();        }        return result;    }

嗯,只要数组的长度不超过int的上限就行。。

test:

public static void main(String[] args){        Integer a[] = {1,1,5,8,6,9,4,7,5,2,6,5,8,5,5,8,6,2};        String s[] = {"s","s","s","t","t","t","t","t","c"};        int resultString = MostFrequent.getMostFrequentByArrayList(s);        int resultInteger = MostFrequent.getMostFrequentByArrayList(a);        System.out.println(resultInteger);        System.out.println(resultString);    }

结果:
5
5

嗯,看来Integer和String都没问题。

不过通过遍历ArrayList将各个元素分配到对应的集合中的办法略显臃肿,性能也不算高。我们知道HashMap查询速度最快,而且使用LinkedList进行添加操作可以避免扩容带来的性能开销。所以这时候可以使用HashMap和LinkedList进行下优化:

/**     * 使用HashMap提高性能。如果是自己定义的类,则要合理重写hashCode和equals方法     * @param a     * @return     */    public static <T> int getMostFrequentByMap(T a[]){        if(a == null||a.length == 0){            return 0;        }        int result = 0;        int size = a.length;        HashMap<T, LinkedList<T>> severalMap = new HashMap<>();        for (int i = 0; i < size; i++) {            T t = a[i];            //以元素本身为键,元素分配到的LinkedList为值            if(severalMap.get(t) != null){                severalMap.get(t).add(t);            }else{                LinkedList<T> temp = new LinkedList<T>();                temp.add(t);                severalMap.put(t, temp);            }        }        //指向长度最大的集合        LinkedList<T> largestList = null;        //找到元素最多的集合        for (LinkedList<T> tempList : severalMap.values()) {            if(largestList == null){                largestList = tempList;                continue;            }            if(tempList.size() > largestList.size()){                largestList = tempList;            }            result = largestList.size();        }           return result;    }

你看,中间那段分配元素就不需要遍历了,直接HsshMap的查询就可以,代码简单速度还更快。

test:

public class Main {    public static void main(String[] args){        Integer a[] = {1,1,5,8,6,9,4,7,5,2,6,5,8,5,5,8,6,2};        String s[] = {"s","s","s","t","t","t","t","t","c"};        int resultInteger = MostFrequent.getMostFrequentByMap(a);        int resultString = MostFrequent.getMostFrequentByMap(s);        System.out.println(resultInteger);        System.out.println(resultString);    }}

结果:
5
5

要注意的是,如果是自己定义的类,要正确重写hashCode和equals方法哦。

0 0
原创粉丝点击