leetcode-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.

Example 1:

Input: [3,2,3]
Output: 3
Example 2:

Input: [2,2,1,1,1,2,2]
Output: 2

思路1:分治法

首先将数组均分成两半,分别找出每一半的主元素。如果两个主元素相等,则直接返回1个;否则遍历完整序列,找到最后赢家:返回出现次数多于一半的那个主元素。
(在某一侧无法分出胜负?没关系,在上一层继续比较,终究会找到最后赢家,因为主元素只有一个。例如[2,2,1,1,1,2,2] 在[2,2,1,1]无法找出部分的主元素,那么随意返回一个,在另一侧[1,2,2]总会找到赢家)
边界条件:序列只有一个元素时,直接返回该元素。
T(n) = 2T(n/2)+O(n)
时间复杂度:O(nlgn)

代码

class Solution {
	//这个方法用来在一定范围内计数
    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;
    }

    private int majorityElementRec(int[] nums, int lo, int hi) {
        // 边界条件
      
        if (lo == hi) {
            return nums[lo];
        }

        // 把数组分为两半进行递归
        int mid = (hi-lo)/2 + lo;
        int left = majorityElementRec(nums, lo, mid);
        int right = majorityElementRec(nums, mid+1, hi);

        // 如果两边主元素相同,返回之
        if (left == right) {
            return left;
        }

        // 否则,遍历数组找到真正的主元素
        int leftCount = countInRange(nums, left, lo, hi);
        int rightCount = countInRange(nums, right, lo, hi);

        return leftCount > rightCount ? left : right;
    }

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

Runtime: 3 ms, faster than 99.43% of Java online submissions for Majority Element.
Memory Usage: 39.2 MB, less than 93.85% of Java online submissions for Majority Element.

思路2:排序法

由题目的性质可以发现,将数组排序后,位于中间的数字一定是主元素。那么使用快排即可。
平均时间复杂度:O(nlgn)

代码

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

Runtime: 3 ms, faster than 99.43% of Java online submissions for Majority Element.
Memory Usage: 41.2 MB, less than 28.89% of Java online submissions for Majority Element.

思路3:投票算法

这是在solution中翻到的答案,十分巧妙。
根据题目的性质,我们知道所要找的主元素的数量比其他数都多,因此将数字可以分成两类,一类是主元素,另一类是“余数”。用一个标记candidate记录某个元素出现的次数,这个元素称为候选者。如果后面的元素和它相同就投票+1,有一个元素和他不相同就投票-1,当candidate小于等于0时,重新记录新的元素。 当遍历完成后,只有真正的主元素会被留下,而其它的余数在过程中总会吃到反对票而失去候选者的资格。

时间复杂度:O(n) 空间复杂度:O(1) 简单粗暴

代码

class Solution {
    public int majorityElement(int[] nums) {
        int count = 0;
        Integer candidate = null;

        for (int num : nums) {
            if (count == 0) {
                candidate = num;
            }
            count += (num == candidate) ? 1 : -1;
        }

        return candidate;
    }
}

Runtime: 4 ms, faster than 71.04% of Java online submissions for Majority Element.
Memory Usage: 41 MB, less than 32.49% of Java online submissions for Majority Element.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值