题目:剑指 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);
    }

}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐