Leetcode#169. Majority Element

题目描述

给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1:

输入: [3,2,3]
输出: 3

示例 2:

输入: [2,2,1,1,1,2,2]
输出: 2

思路

思路一:

利用哈希表的映射,储存数组中的数字以及它们出现的次数,当众数出现时,返回这个数字。

思路二:

因为众数是出现次数大于n/2的数字,所以排序之后中间的那个数字一定是众数。即nums[n/2]为众数。但是在计算比较大的数组时,时间会超过限制。

思路三:

分治法,将整个数组分成两个部分,先分别筛选出这两部分中出现次数最多的数,记为left和right,如果left等于right,则返回left,如果left不等于right,则left和right都是最终结果的候选,此时需要遍历整个数组考察left和right出现的次数,出现次数较多的就是最终返回的结果。

思路四:

摩尔投票算法,先将第一个数字假设为众数,然后把计数器设为1,比较下一个数和此数是否相等,若相等则计数器加一,反之减一。然后看此时计数器的值,若为零,则将当前值设为候选众数。以此类推直到遍历完整个数组,当前候选众数即为该数组的众数。

代码实现

package Array;
import java.util.HashMap;
/**
 * 169\. Majority Element(求众数)
 * 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
 * 你可以假设数组是非空的,并且给定的数组总是存在众数。
 */
public class Solution169 {
    public static void main(String[] args) {
        Solution169 solution169 = new Solution169();
        int[] nums = new int[]{3, 2, 3};
        System.out.println(solution169.majorityElement_4(nums));
    }
    /**
     * 利用哈希表的映射,储存数组中的数字以及它们出现的次数,当众数出现时,返回这个数字。
     *
     * @param nums
     * @return
     */
    public int majorityElement(int[] nums) {
        HashMap map = new HashMap();
        for (int num :
                nums) {
            Integer cnt = map.get(num);
            if (cnt == null) {
                cnt = 1;
            } else {
                cnt++;
            }
            if (cnt > nums.length / 2) {
                return num;
            }
            map.put(num, cnt);
        }
        return 0;
    }
    /**
     * 因为众数是出现次数大于n/2的数字,所以排序之后中间的那个数字一定是众数。即nums[n/2]为众数。但是在计算比较大的数组时,时间会超过限制。
     *
     * @param nums
     * @return
     */
    public int majorityElement_2(int[] nums) {
        int n = nums.length;
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - 1 - i; j++) {
                if (nums[j] > nums[j + 1]) {
                    int temp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = temp;
                }
            }
        }
        return nums[n / 2];
    }
    /**
     * 分治法,将整个数组分成两个部分,先分别筛选出这两部分中出现次数最多的数,记为left和right,如果left等于right,则返回left
     * 如果left不等于right,则left和right都是最终结果的候选,此时需要遍历整个数组考察left和right出现的次数,出现次数较多的就是最终返回的结果。
     *
     * @param nums
     * @return
     */
    public int majorityElement_3(int[] nums) {
        return find(nums, 0, nums.length - 1);
    }
    public int find(int[] nums, int begin, int end) {
        if (begin == end) {
            return nums[begin];
        } else {
            int mid = (begin + end) / 2;
            int left = find(nums, begin, mid);
            int right = find(nums, mid + 1, end);
            //左右两部分的众数相同 则这个数是这部分的众数
            if (left == right) {
                return left;
            } else {
                //左右两部分的众数不相同 则这两个数都有可能是这部分的众数,那么遍历这个数组,看一下哪个数字的出现次数多
                int countLeft = 0;
                int countRight = 0;
                for (int i = begin; i <= end; i++) {
                    if (nums[i] == left) {
                        countLeft++;
                    } else if (nums[i] == right) {
                        countRight++;
                    }
                }
                if (countLeft > countRight) {
                    return left;
                } else {
                    return right;
                }
            }
        }
    }
    /**
     * 摩尔投票算法,先将第一个数字假设为众数,然后把计数器设为1,比较下一个数和此数是否相等,若相等则计数器加一,反之减一。
     * 然后看此时计数器的值,若为零,则将当前值设为候选众数。以此类推直到遍历完整个数组,当前候选众数即为该数组的众数。
     *
     * @param nums
     * @return
     */
    public int majorityElement_4(int[] nums) {
        int maj = nums[0];
        int count = 1;
        for (int num : nums) {
            if (maj == num) {
                count++;
            } else {
                count--;
                if (count == 0) {
                    maj = num;
                    count = 1;
                }
            }
        }
        return maj;
    }
}
全部评论

相关推荐

累死的一条狗:***一人顶10人那你给我发10个人的工资总和吗
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
2025-12-17 16:48
今天九点半到公司,我跟往常一样先扫了眼电脑,屁活儿没有。寻思着没事干,就去蹲了个厕所,回来摸出手机刷了会儿。结果老板刚好路过,拍了我一下说上班别玩手机,我吓得赶紧揣兜里。也就过了四十分钟吧,我的直属领导把我叫到小隔间,上来就给我一句:“你玩手机这事儿把老板惹毛了,说白了,你可以重新找工作了,等下&nbsp;HR&nbsp;会来跟你谈。”&nbsp;我当时脑子直接宕机,一句话都没憋出来。后面&nbsp;HR&nbsp;找我谈话,直属领导也在旁边。HR&nbsp;说我这毛病不是一次两次了,属于屡教不改,不光上班玩手机,还用公司电脑看论文、弄学校的事儿。我当时人都傻了,上班摸鱼是不对,可我都是闲得发慌的时候才摸啊!而且玩手机这事儿,从来没人跟我说过后果这么严重,更没人告诉我在公司学个习也算犯错!连一次口头提醒都没有,哪儿来的屡教不改啊?更让我膈应的是,昨天部门刚开了会,说四个实习生里留一个转正,让大家好好表现。结果今天我就因为玩手机被开了。但搞笑的是,开会前直属领导就把我叫去小会议室,明明白白告诉我:“转正这事儿你就别想了,你的学历达不到我们部门要求,当初招你进来也没打算给你这个机会。”合着我没入贵厂的眼是吧?可我都已经被排除在转正名单外了,摸个鱼至于直接把我开了吗?真的太离谱了!
rush$0522:转正名单没进,大概率本来就没打算留你
摸鱼被leader发现了...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务