LeetCode-229. 多数元素 II-Java-medium

14 篇文章 0 订阅
11 篇文章 0 订阅

题目链接

法一(摩尔投票)
    /**
     * 法一(摩尔投票)
     * 1. 思路
     * (1)每次从序列里选择两个不相同的数字删除掉(或称为“抵消”),最后剩下一个数字或几个相同的数字,就是出现次数大于总数一半的那个
     * (2)摩尔投票算法的核心是求多数元素(可以是多于一半,三分之一,四分之一...)
     * (3)如果至多选1个代表,那他的票数至少要超过⌊1/2⌋的票数
     * (4)如果至多选2个代表,那他们的票数至少要超过⌊1/3⌋的票数
     * (5)如果至多选m个代表,那他们的票数至少要超过⌊1/(m+1)⌋的票数
     * 2. 复杂度
     * 时间复杂度:O(n)
     * 空间复杂度:O(1)
     *
     * @param nums
     * @return
     */
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> ans = new LinkedList<>();
        if (nums == null || nums.length == 0) {
            return ans;
        }
        int x = nums[0], cx = 0; // 初始化两个候选人,和他们的计票
        int y = nums[0], cy = 0;
        for (int num : nums) {
            if (x == num) { // 候选人x投票
                cx++;
                continue;
            }
            if (y == num) { // 候选人y投票
                cy++;
                continue;
            }
            if (cx == 0) {  // 更换候选人
                x = num;
                cx++;
                continue;
            }
            if (cy == 0) {  // 更换候选人
                y = num;
                cy++;
                continue;
            }
            cx--; // 当前元素和两个候选人都不同,则抵消
            cy--;
        }
        cx = 0;
        cy = 0;
        for (int num : nums) { // 计数
            if (x == num) {
                cx++;
            } else if (y == num) {
                cy++;
            }
        }
        if (cx > nums.length / 3) { // 确定候选人x票数是否满足大于len/3
            ans.add(x);
        }
        if (cy > nums.length / 3) { // 确定候选人y票数是否满足大于len/3
            ans.add(y);
        }
        return ans;
    }
法二(哈希)
    /**
     * 法二(哈希)
     * 时间复杂度:O(n)
     * 空间复杂度:O(n)
     *
     * @param nums
     * @return
     */
    public List<Integer> majorityElement_2(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.merge(num, 1, Integer::sum);
        }
        List<Integer> ans = new LinkedList<>();
        int len = nums.length / 3;
        map.forEach((key, value) -> {
            if (value > len) {
                ans.add(key);
            }
        });
        return ans;
    }
法三(排序 + 双指针)
    /**
     * 法三(排序 + 双指针)
     * 时间复杂度:O(nlogn)
     * 空间复杂度:O(1)
     *
     * @param nums
     * @return
     */
    public List<Integer> majorityElement_3(int[] nums) {
        Arrays.sort(nums);
        List<Integer> ans = new LinkedList<>();
        int len = nums.length, left = 0, right = 0;
        while (right < len) {
            while (right < len && nums[left] == nums[right]) {
                right++;
            }
            if (right - left > len / 3) {
                ans.add(nums[left]);
            }
            left = right;
        }
        return ans;
    }
本地测试
        /**
         * 229. 多数元素 II
         */
        lay.showTitle(229);
        Solution229 sol229 = new Solution229();
        int[] nums229 = new int[]{3, 2, 3};
        System.out.println(Arrays.toString(nums229));
        System.out.println(sol229.majorityElement(nums229));
        System.out.println(sol229.majorityElement_2(nums229));
        System.out.println(sol229.majorityElement_3(nums229));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值