【剑指offer】数组中出现次数超过一半的数字

题目:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

思路:
方法一:

定义一个Map集合,key存储数组中出现的数字,value是数字出现的次数。

遍历这个数组,如果当前Map集合为空,直接将第一个数字放入集合,出现次数为1,如果当前集合不为空,且是第一次存储这个数字,依然是直接放入集合,出现次数为1,而如果集合中已经有该数字,将其数量加一就好。

取出所有Map集合中的key值,放入一个List集合中,遍历这个List集合,如果该数字出现的次数大于数组长度的一半,就输出这个数字,List遍历完如果没有找到出现次数大于数组长度一半的数字就输出0。

代码如下:

public class CountNum {
    HashMap<Integer, Integer> map = new HashMap<>();

    public int MoreThanHalfNum_Solution(int[] array) {
        if (array.length == 0 || array == null) {
            return 0;
        }
        for (int i = 0; i < array.length; i++) {
            if (map == null) {
                map.put(array[i], 1);
            } else {
                if (map.containsKey(array[i])) {
                    int count = map.get(array[i]);
                    map.put(array[i], count + 1);
                } else {
                    map.put(array[i], 1);
                }
            }
        }
        
        ArrayList<Map.Entry<Integer, Integer>> list = new ArrayList<>();
        list.addAll(map.entrySet());
        for (Map.Entry<Integer, Integer> entry : list) {
            if (entry.getValue() > array.length / 2) {
                return entry.getKey();
            }
        }
        return 0;

    }
 }

方法二:
这个方法其实是对前一种方法的优化,这次不用遍历这个List集合去查看数字出现的次数,直接将Map里存储的数字按照降序排序,这样List集合里第一个数字就是出现次数最多的数字,如果这个数字出现的次数不大于数组长度的一半,就说明没有数字出现的次数大于数组长度的一半。

看代码:

public class CountNum {
       HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();

    public int MoreThanHalfNum_Solution(int[] array) {
        if (array.length == 0 || array == null) {
            return 0;
        }
        for (int i = 0; i < array.length; i++) {
            if (map == null) {
                map.put(array[i], 1);
            } else {
                if (map.containsKey(array[i])) {
                    //map中已经存有该元素
                    //获取该元素在map有几份,也就是在数组中出现了几次
                    int count = map.get(array[i]);
                    map.put(array[i], count + 1);
                } else {
                    //新元素
                    map.put(array[i], 1);
                }

            }
        }
        //按照值进行排序
        ArrayList<Map.Entry<Integer, Integer>> list = sortMap(map);
        if (list.get(0).getValue() > array.length / 2) {
            return list.get(0).getKey();
        } else {
            return 0;
        }
    }

    public ArrayList<Map.Entry<Integer, Integer>> sortMap(Map map) {
        List<Map.Entry<Integer, Integer>> entries = new ArrayList<Map.Entry<Integer, Integer>>(map.entrySet());
        Collections.sort(entries, new Comparator<Map.Entry<Integer, Integer>>() {
            public int compare(Map.Entry<Integer, Integer> obj1, Map.Entry<Integer, Integer> obj2) {
                return obj2.getValue() - obj1.getValue();
            }
        });
        return (ArrayList<Map.Entry<Integer, Integer>>) entries;
    }
 }

方法三:
这种方法就相当于暴力破解法,我们首先将这个数组进行排序,这样如果存在某个数字的出现次数大于数组长度的一半,那么这个数字一定是新数组中间的那个数字,将这个数字拿出来,遍历数组计算它出现的次数,然后和数组长度的一半进行比较,大于则返回这个数字,不大于返回0。

看代码:

public int MoreThanHalfNum_Solution(int [] array) {
        Arrays.sort(array);
        int len = array.length;
        int num = array[len/2];
        int count = 0;
        for(int i=0; i<len; i++){
            if(array[i] == num){
                count++;
            }
        }
        return count>(len/2)?num:0;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值