• 第2章 数字之魅——数字中的技巧2.3


    2.3寻找发帖“水王”

    问题:求在一个ID列表中出现次数超过一半的ID。

    对于该问题:一个比较直接的想法就是直接统计。统计每个ID出现的次数。然后寻找该数组中最大的数值。从而找出它的ID。

    统计需要N,并且空间上要2*N(而且这里必须保证ID不能是小数而且ID是连续的)。然后对于寻找最大元素。一种是分治。log2 N。一种是建个最大堆。(复杂度)

    当然还有一种就是打擂台。N。

    总体上需要N+N。或者N+log2 N

    另外一种想法是排序后找中间的元素。因为大过一半。所以必然是该ID。利用快排 N*log2 N 很省事。

    而且这个可以推广到那个扩展问题。当元素是大过1/4的时候。那我们只要找下标在3/4的时候即可。

    在编程之美上面,有一个十分巧妙的想法。就是删除2个不同的ID。用来减小问题的规模。(减小问题规模这种思想是我们应该要具备的,这算是一种消元法吧?)

    同时这个想法也是比较容易操作的。而且空间和时间上都有很大的提升,空间是常数的。时间是N的级别。

    当初我不解并且觉得神奇之处在于不同的ID如何实现?一个直观的想法就是用一个 int 型数来保存之前遇到的ID。可是继续思考下去这并不方便。

    那就是维护当前的id。如果下一个遇到的不是这个id就抵消。如果是的话就统计这个id已经出现了2次。最后id保存的一定是出现最多次数的ID。

    //这里假设 ID 是 int 型的,就不用定义Type了, 编程之美上用Type。当然书上更好。
    int Find(int ID,int N)
    {
        /*
        id 就是当前存储的id
        nTimes 代表这个id出现的次数
        */
        int id;
        int nTimes,i;
        nTimes = 0;
        for(i=0;i<N;i++)
        {
            if(nTimes==0)  
            {
                nTimes = 1;
                id = ID[i];
            }
            else
            {
                if(id == ID[i])
                {
                    nTimes ++;
                }
                else
                {
                    nTimes --;
                }
            }
        }
        return id;
    }
    编程之美——优美思想


    反思:这一节的星数是一颗。但是我觉得这里面包含了缩小问题规模的重要思想。正如解决一个难题。我们可以把大化小。解小。而这种缩小问题规模的方法,在编程之美中是屡试不爽的。从求数组的最大值的那一篇章也可以了解到。从而引出了一个重要的算法思想。分治。

  • 相关阅读:
    Lucene 全文检索
    Redis 集群
    Redis 初步接触
    Mybatis
    FastJson 介绍
    JAVA微信企业付款到零钱(十分钟搞定),附完整DEMO下载
    持续集成与Devops关系
    GIT命令行统计代码提交行数
    一种简单的REST API接口加密实现,只允许自己的产品调用后台,防止接口被刷
    Beyond Compare 4.X 破解方法(亲测有效)
  • 原文地址:https://www.cnblogs.com/Milkor/p/4351028.html
Copyright © 2020-2023  润新知