LeetCode169. Majority Element

169.Majority Element

题意:

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.
给定一个长度为 n 的数组,找出 majority元素,majority元素是指出现次数超过 ⌊n/2⌋ 次的元素。

我的思路:

数组元素重复问题,想到用 HashMap,利用 key 表示数组元素,value 表示该数组元素出现的次数,只要次数大于数组长度的一半就可返回该元素。
这道题之所以可以这样做,是因为有假设条件,
* 假设1:非空数组;
* 假设2:大多数元素总是存在;所以不会出现输入为 [1,2,3,4,5,6] 这种情况;

这题的代码中最后的 return -1;永远不会执行。

public int majorityElement(int[] nums) {
    Map<Integer, Integer> map = new HashMap<>();
    int length = nums.length;
    for(int i = 0; i < length; i++){
        if(map.containsKey(nums[i])){
            int val = map.get(nums[i]);
            if(val + 1 > length / 2){
                return nums[i];
            }
            map.put(nums[i], val + 1);
        }else{
            map.put(nums[i], 1);
            if(1 > length / 2){
                return nums[i];
            }
        }
    }
    return -1;   
}

答案:方法一:

这种方法思路和我的思路是一样的,都是用的 HashMap;
但是他多做了一步,就是把遍历完数组的所有元素,然后将数组的所有元素及元素个数放在 Map 中;然后遍历这个 Map ,返回 Map 中 value 值最大的 key 。
时间复杂度:O(n)
空间复杂度:O(n)

public int majorityElement2(int[] nums) {
    Map<Integer, Integer> counts = countNums(nums);
    Map.Entry<Integer, Integer> majorityEntry = null;
    for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
        if (majorityEntry == null || entry.getValue() > majorityEntry.getValue()) {
            majorityEntry = entry;
        }
    }
    return majorityEntry.getKey();
}

private Map<Integer, Integer> countNums(int[] nums) {
    Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
    for (int num : nums) {
        if (!counts.containsKey(num)) {
            counts.put(num, 1);
        }
        else {
            counts.put(num, counts.get(num)+1);
        }
    }
    return counts;
}

答案:方法二:

新的思路2,这种思路真是巧妙。
这种思路也是基于这道题的假设,假设1:数组非空;假设2:数组中一定存在一个大多数元素。
那么我们先将这个数组进行排序,发现,不论数组的长度为偶数还是奇数,大多数元素都会出现在 length/2 的位置 。

    public int majorityElement3(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length/2];
}

答案:方法三:

新的思路3,因为这个数组中有一多半都是我们要找的元素,那么如果我们在数组中随机取一个元素,
那么这个元素就是我们要找的元素的概率很大。
但是这种方法的时间复杂度在最坏的情况下是无穷,只是提供这种思路;
空间复杂度就是O(1)

    public int majorityElement4(int[] nums) {
        Random rand = new Random();

        int majorityCount = nums.length/2;

        while (true) {
            int candidate = nums[randRange(rand, 0, nums.length)];
            if (countOccurences(nums, candidate) > majorityCount) {
                return candidate;
            }
        }
    }
    private int randRange(Random rand, int min, int max) {
        return rand.nextInt(max - min) + min;
    }

    private int countOccurences(int[] nums, int num) {
        int count = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == num) {
                count++;
            }
        }
        return count;
    }

答案:方法四:

新的思路4,分而治之的思想 Divide and Conquer [Accepted]
自己没有看懂
* 时间复杂度:O(nlgn)
* 空间复杂度:O(lgn)

    public int majorityElement5(int[] nums) {
        return majorityElementRec(nums, 0, nums.length-1);
    }

    private int majorityElementRec(int[] nums, int lo, int hi) {
        // base case; the only element in an array of size 1 is the majority
        // element.
        if (lo == hi) {
            return nums[lo];
        }
        // recurse on left and right halves of this slice.
        int mid = (hi-lo)/2 + lo;
        int left = majorityElementRec(nums, lo, mid);
        int right = majorityElementRec(nums, mid+1, hi);
        // if the two halves agree on the majority element, return it.
        if (left == right) {
            return left;
        }
        // otherwise, count each element and return the "winner".
        int leftCount = countInRange(nums, left, lo, hi);
        int rightCount = countInRange(nums, right, lo, hi);
        return leftCount > rightCount ? left : right;
    }

    private int countInRange(int[] nums, int num, int lo, int hi) {
        int count = 0;
        for (int i = lo; i <= hi; i++) {
            if (nums[i] == num) {
                count++;
            }
        }
        return count;
    }

答案:方法五:Boyer-Moore投票算法

这种算法正确的前提是:大多数元素个数超过数组长度的一半。
不同的数之间相互抵消。

    public int majorityElement6(int[] nums){
        int count = 0;
        Integer maj = null;
        for (int i : nums) {
            if(count == 0){
                maj = i;
            }
            count += maj == i ? 1 : -1;
        }
        return maj;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值