剑指 Offer 39. 数组中出现次数超过一半的数字

题目:剑指 Offer 39. 数组中出现次数超过一半的数字

题目链接

https://leetcode-cn.com/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-lcof/

代码连接:

https://gitee.com/aninstein/HappyJava/blob/master/learn_java/src/leetcode/offer100/arrays/EasyMajorityElement.java

解题思路

  1. hash表统计
  2. 排序后用二分查找,左闭右闭的方式进行搜索
  3. 投票假设法

第三种效率最高:
(1)两个推论:

  • 推论一: 若记 众数 的票数为 +1 ,非众数 的票数为 −1 ,则一定有所有数字的 票数和 >0 。
  • 推论二: 若数组的前 a 个数字的 票数和 =0 ,则 数组剩余 (n−a) 个数字的 票数和一定仍 >0 ,即后 (n−a) 个数字的 众数仍为 x 。

(2)一次假设:
根据以上推论,假设数组首个元素 n1​ 为众数,遍历并统计票数。当发生 票数和=0 时,剩余数组的众数一定不变 ,这是由于:

当 n1=x : 抵消的所有数字,有一半是众数 x 。
当 n1≠x : 抵消的所有数字,少于或等于一半是众数 x 。

利用此特性,每轮假设发生 票数和 =0 都可以 缩小剩余数组区间 。当遍历完成时,最后一轮假设的数字即为众数

package leetcode.offer100.arrays;

public class EasyMajorityElement {

    /**
     * 题目:剑指 Offer 39. 数组中出现次数超过一半的数字
     * 题目链接:https://leetcode-cn.com/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-lcof/
     * 1. hash表统计
     * 2. 排序后用二分查找,左闭右闭的方式进行搜索
     * 3. 投票假设法
     *
     * 第三种效率最高:
     * (1)两个推论:
     * - 推论一: 若记 众数 的票数为 +1 ,非众数 的票数为 −1 ,则一定有所有数字的 票数和 >0 。
     * - 推论二: 若数组的前 a 个数字的 票数和 =0 ,则 数组剩余 (n−a) 个数字的 票数和一定仍 >0 ,即后 (n−a) 个数字的 众数仍为 x 。
     *
     * (2)一次假设:
     * 根据以上推论,假设数组首个元素 n1​ 为众数,遍历并统计票数。当发生 票数和=0 时,剩余数组的众数一定不变 ,这是由于:
     *
     *     当 n1=x : 抵消的所有数字,有一半是众数 x 。
     *     当 n1≠x : 抵消的所有数字,少于或等于一半是众数 x 。
     *
     * 利用此特性,每轮假设发生 票数和 =0 都可以 缩小剩余数组区间 。当遍历完成时,最后一轮假设的数字即为众数
     *
     * @param nums
     * @return
     */
    public static int majorityElement(int[] nums) {
        int x = 0, votes = 0;
        for(int num : nums){
            if(votes == 0) {
                x = num;
            }
            votes += num == x ? 1 : -1;
        }
        return x;
    }

    public static void main(String[] args) {
        int[] data = {3,2,3};
        int res = majorityElement(data);
        System.out.println(res);
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值