• [数据结构与算法]15 两行代码就可以搞定求众数,但还有更巧的


    这个周末刷了几道算法题,把其中一个比较不错的分享给你~

    给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
    你可以假设数组是非空的,并且给定的数组总是存在多数元素。

    示例 1:
    输入: [3,2,3]
    输出: 3

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

    哦,原来是求众数,注意一下哈,这里的众数是指"在数组中出现次数大于 ⌊ n/2 ⌋ 的元素",不要问我为什么要你们注意一下这个条件,因为我钻牛角尖了!

    拿到这个题目,我的第一反应就是,那我给这个数组排个序然后取中间的值不就得了?
    所以代码就只有两行:

    Arrays.sort(nums);
    return nums[nums.length >> 1];
    

    写完程序运行,一点儿毛病都没有,简简单单两行代码就搞定,那一刻我觉得我就是个天才!
    后来梦醒了,冷静分析了一下,我去这样的代码简单是简单,但是时间复杂度是 O(nlogn) ,空间复杂度是 O(logn)
    所以有没有更好的解决方案呢?能让它的时间复杂度和空间复杂度都降下来
    必须得有哇!要不然我写这篇文章是为了啥
    这种比较好的解决方案就是摩尔投票法

    这个方法理解起来有点儿绕,我先来讲讲,这一块儿看懂了,咱们再往下走
    先回到现实生活中,投票的时候咱们是怎么投的呢?大家每个人都选一个人,然后开始拆开纸团瞅瞅选的是谁,刚开始默认大家都是 0 票,然后纸条上投的是谁,这个人就多一票,最后看谁的票数比较多.
    回到咱们这个题目,既然是众数,而且出现的次数大于 ⌊ n/2 ⌋ ,那我们可以假设一个数就是要求的众数,同时设置这个数字出现的次数为 0 ,然后和接下来的数字进行比较,如果一样呢,咱们把这个数字出现的次数加上 1 ,如果不一样,就让次数减 1 ,当这个值减到 0 时,说明刚开始假设的数字不是众数,那就换当前的这个数字,继续循环
    这样最后这个数字出现的次数一定是大于等于 0 的,要不然就不符合 出现的次数大于 ⌊ n/2 ⌋ 这个题意了
    最后,将真正的众数返回即可
    具体代码可见下面:

    int count = 0 ;
    Integer candidate = null;
    
        for(int num : nums){
            if (count == 0){
                candidate = num;
            }
            count += ( num == candidate ) ? 1 : -1 ;
        }
    return candidate;
    

    分析一下,这样实现的时间复杂度是 O(n) ,空间复杂度是 O(1)
    和刚开始使用的方法相比,好了许多

    你有没有更巧妙的方法实现,欢迎评论区和我交流哇
    最后,感谢您的阅读~

  • 相关阅读:
    《构建之法》第1.2.3章读后感以及《硅谷传奇》观后感
    算复利条件下等额还款金额
    统计实验数据
    单利计算与复利计算程序
    了解和熟悉操作系统
    0302思考并回答一些问题
    sae storage 使用uploadify插件进行文件批量上传
    PHP页面之间跳转方法总结
    js获取每个按键的ASCII值
    C#文件的拆分与合并操作示例
  • 原文地址:https://www.cnblogs.com/zll-0405/p/12900534.html
Copyright © 2020-2023  润新知