• 求众数[Leetcode]


    求众数有很多种解法,直觉上第一种就是用哈希表统计,这种方法需要O(n)的时间和空间。另一种叫摩尔投票法,需要O(n)的时间和O(1)的空间,比哈希表要好,这种投票法先将第一个数字假设为众数,然后把计数器设为1,比较下一个数和此数是否相等,若相等则计数器加1,否则计数器减1.然后看此时计数器的值,若为0,则将下一个值设为候选众数。以此类推直到遍历完整个数组,当前候选众数即为该数组的众数。精妙!通俗的讲,他是把原数组精简化,相互抵消。首先是有个强大的前提存在,就是众数一定存在。如果计数器减到0了,说明目前不是候选者的数字的个数已经跟候选者出现的个数相同了,那么这个候选者已经很weak,不一定能出现超过半数,我们选择更换当前的候选者。那么可能你会有疑问,那万一后面又大量出现了之前的候选者怎么办,不需要担心,如果之前的候选者在后面大量出现的话,其又会重新变为候选者,直到最终验证成为正确的众数,佩服算法的提出者啊,代码如下:

    class Solution {
        public int majorityElement(int[] nums) {
            int cnt = 1;
            int res = nums[0];
            for(int i=1;i<nums.length;i++){ 
            //也可直接遍历数组for(int num:nums)
                if(cnt == 0){
                    res = nums[i];
                }
                else if(res == nums[i]) ++cnt;
                else --cnt;             
            }
            return res;
        }
    }    

    还有一种解法用到了位操作,将众按位来建立,从0到31位,每次统计下数组中该位上0和1的个数,如果1多,那么我们将结果res中该位变为1,最后累加出来的res就是众数了,相当赞的方法,这种思路尤其在这道题的延伸Majority Element II中有重要的应用,参见代码如下:

    public class Solution {
        public int majorityElement(int[] nums) {
            int res = 0, n = nums.length;
            for (int i = 0; i < 32; ++i) {
                int ones = 0, zeros = 0;
                for (int num : nums) {
                    if (ones > n / 2 || zeros > n / 2) break;
                    if ((num & (1 << i)) != 0) ++ones;
                    else ++zeros;
                }
                if (ones > zeros) res |= (1 << i);
            }
            return res;
        }
    }

    或许这就是带佬的操作8。

  • 相关阅读:
    结对开发第一阶段,10天冲刺第十天
    结对开发第一阶段,10天冲刺第九天
    vim 编辑器
    用户、群组和权限
    硬盘分区、格式化及文件系统管理
    系统监控
    Linux 系统初始化和服务
    文件合并与打包
    计算机原理
    Linux 之添加系统环境变量
  • 原文地址:https://www.cnblogs.com/zhlz/p/10486072.html
Copyright © 2020-2023  润新知