169. 求众数

题目

169. 求众数_第1张图片

解析

一道求众数的题目,原先的想法很简单,求出每一个数字出现的次数并放入一个数组中,最后再遍历该数组找到最大的即可,(所以就出现了定义一个类,包含val和count两个属性,然后再创建对象放入集合中一一比较这种非常非常慢的算法,虽然可以实现结果,但是却耗费了很多时间),后来我利用了hashmap,大致思路和刚才说的一样,算法如下:(当然也超时了)

    public int majorityElement(int[] nums) {
        Map map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int count = 0;
            for (int j = i; j < nums.length; j++) {
                if (nums[i] == nums[j]) {
                    count++;
                }
            }
            map.put(nums[i], count);
        }
        Iterator iter = map.entrySet().iterator();
        int max = 0;
        int maxNum = nums[0];
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            Object key = entry.getKey();
            Object val = entry.getValue();
            if ((int) val > max) {
                max = (int) val;
                maxNum = (int) key;
            }
        }
        return maxNum;
    }

最后我在查资料的时候发现了一种新的算法——“摩尔投票法”

程序开始之前,元素c为空,f(c)=0。遍历数组A:

  • 如果f(c)为0,表示截至到当前子数组,并没有候选元素。也就是说之前的遍历过程中并没有找到超过半数的元素。那么,如果超过半数的元素c存在,那么c在剩下的子数组中,出现次数也一定超过半数。因此我们可以将原始问题转化为它的子问题。此时c赋值为当前元素, 同时f(c)=1。
  • 如果当前元素A[i] == c, 那么f(c) += 1。(没有找到不同元素,只需要把相同元素累计起来)
  • 如果当前元素A[i] != c,那么f(c) -= 1 (相当于删除1个c),不对A[i]做任何处理(相当于删除A[i])
  • 如果遍历结束之后,f(c)不为0,则找到可能元素。
  • 再次遍历一遍数组,记录c真正出现的次数,从而验证c是否真的出现了超过半数。上述算法的时间复杂度为O(n),而由于并不需要真的删除数组元素,我们也并不需要额外的空间来保存原始数组,空间复杂度为O(1)。
    代码如下:
    /**
     * 算法基础:摩尔投票法
     *
     * @param nums
     * @return
     */
    public int majorityElement(int[] nums) {

        int majority = -1;

        int count = 0;

        for (int num : nums) {
            if (count == 0) {
                majority = num;
                count++;
            } else {
                if (majority == num) {
                    count++;
                } else {
                    count--;
                }
            }
        }

        int counter = 0;
        if (count <= 0) {
            return -1;
        } else {
            for (int num : nums) {
                if (num == majority) counter++;
            }
        }

        if (counter > nums.length / 2) {
            return majority;
        }

        return -1;
    }

你可能感兴趣的:(169. 求众数)