精华内容
下载资源
问答
  • 2019-07-15 17:50:34

    top K问题

            在大规模数据处理中,经常会遇到的一类问题:在海量数据中找出出现频率最好的前k个数,或者从海量数据中找出最大的前k个数,这类问题通常被称为top K问题。例如,在搜索引擎中,统计搜索最热门的10个查询词;在歌曲库中统计下载最高的前10首歌等。

            针对top K类问题,通常比较好的方案是分治+Trie树/hash+小顶堆(就是上面提到的最小堆),即先将数据集按照Hash方法分解成多个小数据集,然后使用Trie树活着Hash统计每个小数据集中的query词频,之后用小顶堆求出每个数据集中出现频率最高的前K个数,最后在所有top K中求出最终的top K。

    eg:有1亿个浮点数,如果找出期中最大的10000个?

            最容易想到的方法是将数据全部排序,然后在排序后的集合中进行查找,最快的排序算法的时间复杂度一般为O(nlogn),如快速排序。但是在32位的机器上,每个float类型占4个字节,1亿个浮点数就要占用400MB的存储空间,对于一些可用内存小于400M的计算机而言,很显然是不能一次将全部数据读入内存进行排序的。其实即使内存能够满足要求(我机器内存都是8GB),该方法也并不高效,因为题目的目的是寻找出最大的10000个数即可,而排序却是将所有的元素都排序了,做了很多的无用功。

            第二种方法为局部淘汰法,该方法与排序方法类似,用一个容器保存前10000个数,然后将剩余的所有数字——与容器内的最小数字相比,如果所有后续的元素都比容器内的10000个数还小,那么容器内这个10000个数就是最大10000个数。如果某一后续元素比容器内最小数字大,则删掉容器内最小元素,并将该元素插入容器,最后遍历完这1亿个数,得到的结果容器中保存的数即为最终结果了。此时的时间复杂度为O(n+m^2),其中m为容器的大小,即10000。

            第三种方法是分治法,将1亿个数据分成100份,每份100万个数据,找到每份数据中最大的10000个,最后在剩下的100*10000个数据里面找出最大的10000个。如果100万数据选择足够理想,那么可以过滤掉1亿数据里面99%的数据。100万个数据里面查找最大的10000个数据的方法如下:用快速排序的方法,将数据分为2堆,如果大的那堆个数N大于10000个,继续对大堆快速排序一次分成2堆,如果大的那堆个数N大于10000个,继续对大堆快速排序一次分成2堆,如果大堆个数N小于10000个,就在小的那堆里面快速排序一次,找第10000-n大的数字;递归以上过程,就可以找到第1w大的数。参考上面的找出第1w大数字,就可以类似的方法找到前10000大数字了。此种方法需要每次的内存空间为10^6*4=4MB,一共需要101次这样的比较。

            第四种方法是Hash法。如果这1亿个书里面有很多重复的数,先通过Hash法,把这1亿个数字去重复,这样如果重复率很高的话,会减少很大的内存用量,从而缩小运算空间,然后通过分治法或最小堆法查找最大的10000个数。

            第五种方法采用最小堆。首先读入前10000个数来创建大小为10000的最小堆,建堆的时间复杂度为O(mlogm)(m为数组的大小即为10000),然后遍历后续的数字,并于堆顶(最小)数字进行比较。如果比最小的数小,则继续读取后续数字;如果比堆顶数字大,则替换堆顶元素并重新调整堆为最小堆。整个过程直至1亿个数全部遍历完为止。然后按照中序遍历的方式输出当前堆中的所有10000个数字。该算法的时间复杂度为O(nmlogm),空间复杂度是10000(常数)。

    实际运行:

            实际上,最优的解决方案应该是最符合实际设计需求的方案,在时间应用中,可能有足够大的内存,那么直接将数据扔到内存中一次性处理即可,也可能机器有多个核,这样可以采用多线程处理整个数据集。

           下面针对不容的应用场景,分析了适合相应应用场景的解决方案。

    (1)单机+单核+足够大内存

            如果需要查找10亿个查询次(每个占8B)中出现频率最高的10个,考虑到每个查询词占8B,则10亿个查询次所需的内存大约是10^9 * 8B=8GB内存。如果有这么大内存,直接在内存中对查询次进行排序,顺序遍历找出10个出现频率最大的即可。这种方法简单快速,使用。然后,也可以先用HashMap求出每个词出现的频率,然后求出频率最大的10个词。

    (2)单机+多核+足够大内存

            这时可以直接在内存总使用Hash方法将数据划分成n个partition,每个partition交给一个线程处理,线程的处理逻辑同(1)类似,最后一个线程将结果归并。

            该方法存在一个瓶颈会明显影响效率,即数据倾斜。每个线程的处理速度可能不同,快的线程需要等待慢的线程,最终的处理速度取决于慢的线程。而针对此问题,解决的方法是,将数据划分成c×n个partition(c>1),每个线程处理完当前partition后主动取下一个partition继续处理,知道所有数据处理完毕,最后由一个线程进行归并。

    (3)单机+单核+受限内存

            这种情况下,需要将原数据文件切割成一个一个小文件,如次啊用hash(x)%M,将原文件中的数据切割成M小文件,如果小文件仍大于内存大小,继续采用Hash的方法对数据文件进行分割,知道每个小文件小于内存大小,这样每个文件可放到内存中处理。采用(1)的方法依次处理每个小文件。

    (4)多机+受限内存

            这种情况,为了合理利用多台机器的资源,可将数据分发到多台机器上,每台机器采用(3)中的策略解决本地的数据。可采用hash+socket方法进行数据分发。

            从实际应用的角度考虑,(1)(2)(3)(4)方案并不可行,因为在大规模数据处理环境下,作业效率并不是首要考虑的问题,算法的扩展性和容错性才是首要考虑的。算法应该具有良好的扩展性,以便数据量进一步加大(随着业务的发展,数据量加大是必然的)时,在不修改算法框架的前提下,可达到近似的线性比;算法应该具有容错性,即当前某个文件处理失败后,能自动将其交给另外一个线程继续处理,而不是从头开始处理。
            top K问题很适合采用MapReduce框架解决,用户只需编写一个Map函数和两个Reduce 函数,然后提交到Hadoop(采用Mapchain和Reducechain)上即可解决该问题。具体而言,就是首先根据数据值或者把数据hash(MD5)后的值按照范围划分到不同的机器上,最好可以让数据划分后一次读入内存,这样不同的机器负责处理不同的数值范围,实际上就是Map。得到结果后,各个机器只需拿出各自出现次数最多的前N个数据,然后汇总,选出所有的数据中出现次数最多的前N个数据,这实际上就是Reduce过程。对于Map函数,采用Hash算法,将Hash值相同的数据交给同一个Reduce task;对于第一个Reduce函数,采用HashMap统计出每个词出现的频率,对于第二个Reduce 函数,统计所有Reduce task,输出数据中的top K即可。
            直接将数据均分到不同的机器上进行处理是无法得到正确的结果的。因为一个数据可能被均分到不同的机器上,而另一个则可能完全聚集到一个机器上,同时还可能存在具有相同数目的数据。

    以下是一些经常被提及的该类问题。

    (1)有10000000个记录,这些查询串的重复度比较高,如果除去重复后,不超过3000000个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。请统计最热门的10个查询串,要求使用的内存不能超过1GB。
    (2)有10个文件,每个文件1GB,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。按照query的频度排序。
    (3)有一个1GB大小的文件,里面的每一行是一个词,词的大小不超过16个字节,内存限制大小是1MB。返回频数最高的100个词。
    (4)提取某日访问网站次数最多的那个IP。
    (5)10亿个整数找出重复次数最多的100个整数。
    (6)搜索的输入信息是一个字符串,统计300万条输入信息中最热门的前10条,每次输入的一个字符串为不超过255B,内存使用只有1GB。
    (7)有1000万个身份证号以及他们对应的数据,身份证号可能重复,找出出现次数最多的身份证号。

    重复问题

            在海量数据中查找出重复出现的元素或者去除重复出现的元素也是常考的问题。针对此类问题,一般可以通过位图法实现。例如,已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同号码的个数。
            本题最好的解决方法是通过使用位图法来实现。8位整数可以表示的最大十进制数值为99999999。如果每个数字对应于位图中一个bit位,那么存储8位整数大约需要99MB。因为1B=8bit,所以99Mbit折合成内存为99/8=12.375MB的内存,即可以只用12.375MB的内存表示所有的8位数电话号码的内容。

    更多相关内容
  • 满意答案lwchfqz2018.10.24采纳率:46%等级:6已帮助:157人首先,你的程序由于定义了变量a,又定义了数组a,而...其中一很明显的错误就是第7行i=1,数组是从下标0开始,很明显你只能存储2个数。经过一番调试,如果...

    满意答案

    00e27ab806e4881f8254fe7ae8741834.png

    lwchfqz

    2018.10.24

    00e27ab806e4881f8254fe7ae8741834.png

    采纳率:46%    等级:6

    已帮助:157人

    首先,你的程序由于定义了变量a,又定义了数组a,而此时数组名a不是变量,与前面定义的变量a重复,只要把数组名a改成非a,b,c,maax,min,i,j的其他字母就行啦但是修改后的程序只能输入数据,不能输出结果。其中一个很明显的错误就是第7行i=1,数组是从下标0开始,很明显你只能存储2个数。经过一番调试,如果你非得用数组解题,可用如下程序:#include

    void main()

    {

    int i,j,a[3],t;for (i=0;i<3;i++)

    {printf("请输入第%d个数的值:",i+1);scanf("%d",&a[i]);printf("\n");}for(i=0;i<2;i++)

    for(j=i+1;j<=2;j++)

    if(a[i]

    {

    t=a[i];

    a[i]=a[j];

    a[j]=t;

    }printf("最大值为%d\n",a[0]);

    printf("最小值为%d\n",a[2]);

    }程序结果: 对于你后来问到的为什么改后的程序没错而能运行的问题,是因为你定义了一个含有三个元素的数组,而元素下标只能从0-2,而你编的时候刚好写多了一个a3,所以程序对于a1和a2还能分配存储空间,但是对于a3这个额外生出的数据就不知道往哪里存储;还有,你下面进行比较是从a0开始,而这个变量又没分配数值,无法进行比较,所以就无法输出结果 如果你真的很想用abc三个变量和if语句,那么下面这个程序应该适合你,程序如下:#include

    void main()

    {

    int a,b,c,t;

    printf("输入a、b、c的值(用空格分开):");

    scanf("%d %d %d",&a,&b,&c);

    if(a

    if(a

    if(b

    printf("最大数:%d\n",a);

    printf("最小数:%d\n",c);

    }程序结果: 这种题目我看用if语句就最简单啦,至于用到数组和函数调用就有点大题小做。其实函数调用只是if语句的浓缩。

    00分享举报

    展开全文
  • 某年某月某日,老师给我们布置了一极其笨拙的方法用来求三个数中最大值,还在最后让我们找其他方法,这就让我瞬间上了头! 第一种-使用三元运算符如名字表示的三元运算符需要三操作。语法为:条件表达式?...

    写在前面:这里是小王成长日志,一名在校大学生,想在学习之余将自己的学习笔记分享出来,记录自己的成长轨迹,帮助可能需要的人。欢迎关注与留言。

    某年某月某日,老师给我们布置了一个极其笨拙的方法用来求三个数中的最大值,还在最后让我们找其他方法,这就让我瞬间上了头!

    aabc331ada4829180bacf9327ff3a2d0.png

    第一种-使用三元运算符

    如名字表示的三元运算符需要三个操作数。

    语法为:条件表达式?表达式1:表达式2。

    说明:问号前面的位置是判断的条件,判断结果为bool型,为true时调用表达式1,为false时调用表达式2。

    其逻辑为:“如果条件表达式成立或者满足则执行表达式1,否则执行第二个。”常用在设置默认值,例如某个值不一定存在,则判断这个值是否存在,不存在给默认值(表达式2)。

    这题我们的思路也是一样,在这里我们先用三元运算符求出两个数的最大值,然后用这个最大值与第三个数比较得出真正的最大值。

    #include

    int main()

    {

    int a, b, c;

    printf("请输入a,b,c");

    scanf("%d %d %d", &a, &b, &c);

    // 1.三元运算符

    int n = (((a > b) ? a : b) > c) ? ((a > b) ? a : b) : c;

    printf("%d", n);

    return 0;

    }

    第二种-调用函数

    其实调用的函数实际上又可以有多种写法,但是这里就不展开了,基本就是这里的方法变成两个数求最大值套进去,相信各位聪明的看官一定能轻松理解的。

    #include

    int main()

    {

    int a, b, c;

    printf("请输入a,b,c");

    scanf("%d %d %d", &a, &b, &c);

    // 2.调用函数

    int m=judge(judge(a,b),c);

    printf("%d", m);

    }

    int judge(int a, int b)

    {

    return (a > b) ? a : b;

    }

    第三种-使用中间变量储存最大值

    // 3.使用中间变量储存最大值

    #include

    int main()

    {

    int a, b, c;

    printf("请输入a,b,c");

    scanf("%d %d %d", &a, &b, &c);

    int t = 0;

    if (a > b)

    t = a;

    else

    t = b;

    if (c > t)

    t = c; //t为最大值

    printf("%d", c);

    }

    第四种-方法3的改进版-使用a储存最大值

    // 4.方法3的改进版-使用a储存最大值

    #include

    int main()

    {

    int a, b, c;

    printf("请输入a,b,c");

    scanf("%d %d %d", &a, &b, &c);

    if (a

    a=b;

    if (a

    a=c;//a值为最大值

    printf("%d",a);

    }

    第五种-使用&&防止if嵌套

    // 5.使用&&防止if嵌套

    #include

    int main()

    {

    int a, b, c;

    printf("请输入a,b,c");

    scanf("%d %d %d", &a, &b, &c);

    int max;

    if (a > b && a > c)

    max = a;

    else if

    max = b;

    else

    max = c;

    printf("%d",max);

    }

    都看到这里了,各位哥哥姐姐叔叔阿姨给小王点个赞 关个注 留个言吧,和小王一起成长吧,你们的关注是对我最大的支持。

    有事没事进来看看吧 : 小王的博客目录索引

    更多计算机网络优质博客看这 : 计算机网络专栏博客索引

    如果以上内容有任何不准确或遗漏之处,或者你有更好的意见,就在下面留个言让我知道吧-我会尽我所能来回答。

    展开全文
  • 如何在1亿个数中找出最大的100个数(top K问题) ​ 最容易想到的方法是将数据全部排序,然后在排序后的集合进行查找,最快的排序算法的时间复杂度一般为O(nlogn),如快速排序。但是在32位的机器上,每float...

    如何在1亿个数中找出最大的100个数(top K问题)

    ​ 最容易想到的方法是将数据全部排序,然后在排序后的集合中进行查找,最快的排序算法的时间复杂度一般为O(nlogn),如快速排序。但是在32位的机器上,每个float类型占4个字节,1亿个浮点数就要占用400MB的存储空间,对于一些可用内存小于400M的计算机而言,很显然是不能一次将全部数据读入内存进行排序的。其实即使内存能够满足要求(我机器内存都是8GB),该方法也并不高效,因为题目的目的是寻找出最大的10000个数即可,而排序却是将所有的元素都排序了,做了很多的无用功。

    ​ 第二种方法为局部淘汰法,该方法与排序方法类似,用一个容器保存前10000个数,然后将剩余的所有数字——与容器内的最小数字相比,如果所有后续的元素都比容器内的10000个数还小,那么容器内这个10000个数就是最大10000个数。如果某一后续元素比容器内最小数字大,则删掉容器内最小元素,并将该元素插入容器,最后遍历完这1亿个数,得到的结果容器中保存的数即为最终结果了。此时的时间复杂度为O(n+m^2),其中m为容器的大小,即10000。

    ​ 第三种方法是分治法,将1亿个数据分成100份,每份100万个数据,找到每份数据中最大的10000个,最后在剩下的10010000个数据里面找出最大的10000个。如果100万数据选择足够理想,那么可以过滤掉1亿数据里面99%的数据。100万个数据里面查找最大的10000个数据的方法如下:用快速排序的方法,将数据分为2堆,如果大的那堆个数N大于10000个,继续对大堆快速排序一次分成2堆,如果大的那堆个数N大于10000个,继续对大堆快速排序一次分成2堆,如果大堆个数N小于10000个,就在小的那堆里面快速排序一次,找第10000-n大的数字;递归以上过程,就可以找到第1w大的数。参考上面的找出第1w大数字,就可以类似的方法找到前10000大数字了。此种方法需要每次的内存空间为10^64=4MB,一共需要101次这样的比较。*

    ​ 第四种方法是Hash法。如果这1亿个书里面有很多重复的数,先通过Hash法,把这1亿个数字去重复,这样如果重复率很高的话,会减少很大的内存用量,从而缩小运算空间,然后通过分治法或最小堆法查找最大的10000个数。

    ​ 第五种方法采用最小堆。首先读入前10000个数来创建大小为10000的最小堆,建堆的时间复杂度为O(mlogm)(m为数组的大小即为10000),然后遍历后续的数字,并于堆顶(最小)数字进行比较。如果比最小的数小,则继续读取后续数字;如果比堆顶数字大,则替换堆顶元素并重新调整堆为最小堆。整个过程直至1亿个数全部遍历完为止。然后按照中序遍历的方式输出当前堆中的所有10000个数字。该算法的时间复杂度为O(nmlogm),空间复杂度是10000(常数)。

    实际运行:

    ​ 实际上,最优的解决方案应该是最符合实际设计需求的方案,在时间应用中,可能有足够大的内存,那么直接将数据扔到内存中一次性处理即可,也可能机器有多个核,这样可以采用多线程处理整个数据集。

    ​ 下面针对不容的应用场景,分析了适合相应应用场景的解决方案。

    (1)单机+单核+足够大内存
    ​ 如果需要查找10亿个查询次(每个占8B)中出现频率最高的10个,考虑到每个查询词占8B,则10亿个查询次所需的内存大约是10^9 * 8B=8GB内存。如果有这么大内存,直接在内存中对查询次进行排序,顺序遍历找出10个出现频率最大的即可。这种方法简单快速,使用。然后,也可以先用HashMap求出每个词出现的频率,然后求出频率最大的10个词。

    (2)单机+多核+足够大内存
    ​ 这时可以直接在内存总使用Hash方法将数据划分成n个partition,每个partition交给一个线程处理,线程的处理逻辑同(1)类似,最后一个线程将结果归并。

    ​ 该方法存在一个瓶颈会明显影响效率,即数据倾斜。每个线程的处理速度可能不同,快的线程需要等待慢的线程,最终的处理速度取决于慢的线程。而针对此问题,解决的方法是,将数据划分成c×n个partition(c>1),每个线程处理完当前partition后主动取下一个partition继续处理,知道所有数据处理完毕,最后由一个线程进行归并。

    (3)单机+单核+受限内存
    ​ 这种情况下,需要将原数据文件切割成一个一个小文件,如次啊用hash(x)%M,将原文件中的数据切割成M小文件,如果小文件仍大于内存大小,继续采用Hash的方法对数据文件进行分割,知道每个小文件小于内存大小,这样每个文件可放到内存中处理。采用(1)的方法依次处理每个小文件。

    (4)多机+受限内存
    ​ 这种情况,为了合理利用多台机器的资源,可将数据分发到多台机器上,每台机器采用(3)中的策略解决本地的数据。可采用hash+socket方法进行数据分发。

    ​ 从实际应用的角度考虑,(1)(2)(3)(4)方案并不可行,因为在大规模数据处理环境下,作业效率并不是首要考虑的问题,算法的扩展性和容错性才是首要考虑的。算法应该具有良好的扩展性,以便数据量进一步加大(随着业务的发展,数据量加大是必然的)时,在不修改算法框架的前提下,可达到近似的线性比;算法应该具有容错性,即当前某个文件处理失败后,能自动将其交给另外一个线程继续处理,而不是从头开始处理。

    ​ top K问题很适合采用MapReduce框架解决,用户只需编写一个Map函数和两个Reduce 函数,然后提交到Hadoop(采用Mapchain和Reducechain)上即可解决该问题。具体而言,就是首先根据数据值或者把数据hash(MD5)后的值按照范围划分到不同的机器上,最好可以让数据划分后一次读入内存,这样不同的机器负责处理不同的数值范围,实际上就是Map。得到结果后,各个机器只需拿出各自出现次数最多的前N个数据,然后汇总,选出所有的数据中出现次数最多的前N个数据,这实际上就是Reduce过程。对于Map函数,采用Hash算法,将Hash值相同的数据交给同一个Reduce task;对于第一个Reduce函数,采用HashMap统计出每个词出现的频率,对于第二个Reduce 函数,统计所有Reduce task,输出数据中的top K即可。

    ​ 直接将数据均分到不同的机器上进行处理是无法得到正确的结果的。因为一个数据可能被均分到不同的机器上,而另一个则可能完全聚集到一个机器上,同时还可能存在具有相同数目的数据。

    以下是一些经常被提及的该类问题。

    (1)有10000000个记录,这些查询串的重复度比较高,如果除去重复后,不超过3000000个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。请统计最热门的10个查询串,要求使用的内存不能超过1GB。

    (2)有10个文件,每个文件1GB,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。按照query的频度排序。

    (3)有一个1GB大小的文件,里面的每一行是一个词,词的大小不超过16个字节,内存限制大小是1MB。返回频数最高的100个词。

    (4)提取某日访问网站次数最多的那个IP。

    (5)10亿个整数找出重复次数最多的100个整数。

    (6)搜索的输入信息是一个字符串,统计300万条输入信息中最热门的前10条,每次输入的一个字符串为不超过255B,内存使用只有1GB。

    (7)有1000万个身份证号以及他们对应的数据,身份证号可能重复,找出出现次数最多的身份证号。

    重复问题
    ​ 在海量数据中查找出重复出现的元素或者去除重复出现的元素也是常考的问题。针对此类问题,一般可以通过位图法实现。例如,已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同号码的个数。

    ​ 本题最好的解决方法是通过使用位图法来实现。8位整数可以表示的最大十进制数值为99999999。如果每个数字对应于位图中一个bit位,那么存储8位整数大约需要99MB。因为1B=8bit,所以99Mbit折合成内存为99/8=12.375MB的内存,即可以只用12.375MB的内存表示所有的8位数电话号码的内容。

    算法一:冒泡排序法

    千里之行,始于足下。我们先不说最好,甚至不说好。我们只问,如何“从10000个整数中找出最大的10个”?我最先想到的是用冒泡排序的办法:我们从头到尾走10趟,自然会把最大的10个数找到。方法简单,就不再这里写代码了。这个算法的复杂度是10N(N=10000)。

    算法二:

    有没有更好一点的算法呢?当然。维持一个长度为10的降序数组,每一个从数组拿到的数字都与这个降序数组的最小值比较。如果小于最小值,就舍弃;如果大于最小值,就把它插入到降序数组中的合适位置,舍弃原来的最小值。这样,遍历一遍就可以找到最大的10个数。因为需要在降序数组中插入一个数,对于遍历的每个数可能都需要这样,所以其复杂为5N。

    伪代码如下:

      A[N],a[m](分别为原始数组和降序数组,其中N=10000,m=10)
    
      a = A[0 ... 9](将数组A的前10个数赋给数组a)
    
      sort a(将组数a降序排序)
    
      for i in A[ 10 ... N](从10到N遍历数组A)
    
        if A[i] > a[9] then (如果当前值比降序数组中的最小值大)
    
          删除a[9]
    
          将A[i]插入a的合适位置,使a保持降序
    
        end if
    
      end for
    
      输出数组a
    
    

    其实算法二还有一个优点,就是当数组很大时,可以将数据分段读入内存处理,而这样做并不影响结果。

    1、首先一点,对于海量数据处理,思路基本上是确定的,必须分块处理,然后再合并起来。

    2、对于每一块必须找出10个最大的数,因为第一块中10个最大数中的最小的,可能比第二块中10最大数中的最大的还要大。

    3、分块处理,再合并。也就是Google MapReduce 的基本思想。Google有很多的服务器,每个服务器又有很多的CPU,因此,100亿个数分成100块,每个服务器处理一块,1亿个数分成100块,每个CPU处理一块。然后再从下往上合并。注意:分块的时候,要保证块与块之间独立,没有依赖关系,否则不能完全并行处理,线程之间要互斥。另外一点,分块处理过程中,不要有副作用,也就是不要修改原数据,否则下次计算结果就不一样了。

    4、上面讲了,对于海量数据,使用多个服务器,多个CPU可以并行,显著提高效率。对于单个服务器,单个CPU有没有意义呢?

    也有很大的意义。如果不分块,相当于对100亿个数字遍历,作比较。这中间存在大量的没有必要的比较。可以举个例子说明,全校高一有100个班,我想找出全校前10名的同学,很傻的办法就是,把高一100个班的同学成绩都取出来,作比较,这个比较数据量太大了。应该很容易想到,班里的第11名,不可能是全校的前10名。也就是说,不是班里的前10名,就不可能是全校的前10名。因此,只需要把每个班里的前10取出来,作比较就行了,这样比较的数据量就大大地减少了。

    之前看到一个面试题,1000个乱序正整数中找出10个最小值,要求高效快速,不能使用API。

    ​ 这学期学了些排序的方法,什么快速排序啊,冒泡啊,归并排序啊之类的。看到这个题的时候,第一反应是快速排序,因为它的名字叫快速嘛,应该够快吧。然后又想到这个题目不是要你完整的排序,只需要求出最小的10个就够了,那么冒泡法呢?冒泡法只冒前面10个数?

    ​ 发现这样子还是要遍历比较1000*10次。

    ​ 然后,利用类似于数据结构里的栈的特性?把这1000个数的前10个放到一个数组中,排好序,然后,剩下的990个数字,每个都与这10个数的最大数比较,大于则不考虑,小于就把最大值拿出来,把这个数放进去,这样的话,冒泡排序的比较次数就变成了990次,好像高效很多哦?

    展开全文
  • 从10亿数字找出最大的前100个数

    千次阅读 2020-06-06 17:28:35
    先拿10000个数建堆,然后一次添加剩余元素,如果大于堆顶的(10000最小的),将这个数替换堆顶,并调整结构使之仍然是一最小堆,这样,遍历完后,堆的10000个数就是所需的最大的10000。建堆时间复杂度是O...
  • 用C语言编写程序,输入一正整数n(1#include"stdio.h"intmain(){\x09inti,j,n;\x09inta[12];...i编写一C语言程序,输入abc三值,求最大者给,最简代码:#includevoidmain(){inta,b,c,max;scanf("%d%d%d",&...
  • “在输入的十数字最大和最小值的 python 代码”这需求,在不同时间来看,解题思路不同,所需要的 python 知识点不同。作为萌新的我,为此特意整理了 3 种解法,以及相应的知识点笔记。解法A:不使用列表、...
  • 这道题的思路是,先拿10000个数建堆,然后一次添加剩余元素,如果大于堆顶的(10000最小的),将这个数替换堆顶,并调整结构使之仍然是一最小堆,这样,遍历完后,堆的10000个数就是所需的最大的10000。...
  • 组合的数字数是相同的,如果需要求得最大值,高位的数字越大越好,所以需要在给定的数字,选择最高位最大的数字放到最前面。这样得出的数值最高位比其他组合要大。所以比较的标准就是最高位的大小,如果最高位...
  • 2.编写一C程序,运行时输入a,b,c三值,输出...思路:先比较两个数的大小,然后将较大的再与第三个数比较,最后输出最大值。 代码如下: #include &lt;stdio.h&gt; //编译预处理命令 int main() ...
  •  Python——无序数组找出和为N的两个(三个四个数) 【问题描述】无序数组找出和为N的两个,例如,nums = [1, 4, 3, 2, 6, 5]找出和为target = 6的序列,答案:[(1, 5), (4, 2)]。 参考博客: 1、...
  • 重载(在一程序可以定义多名称相同的方法,但是参数的类型和个数必须不同) Java针对同一类: 1、方法名相同 2、方法的参数不同(参数个数或者参数类型) 3、方法的返回值类型不影响重载. 使用重载时,输入的...
  • 方法一、先拿10000个数建堆,然后一次添加剩余元素,如果大于堆顶的(10000最小的),将这个数替换堆顶,并调整结构使之仍然是一最小堆,这样,遍历完后,堆的10000个数就是所需的最大的10000。...
  • python如何求解两最大公约数

    千次阅读 2020-12-04 14:49:15
    分析:单看题目的话,非常简单,我们可以循环遍历自然数,如果能够整除两自然数,就把这个数记下来,在这些记录找到最大的一。但是这样做有几缺点:一是做除法计算量比较大,二是遍历所有自然数完全没有必要...
  • Python 输入三整数,输出最大

    千次阅读 2020-11-20 23:52:24
    0 465 2019-12-06 14:02 − 学习提纲 生成指定范围的数值列表,语法格式如下: 生成一包括10哥随机数的列表,要求的范围在10-100之间,代码如下 import random randomnumber = [random.randint(10,100) for i ...
  • 四个数比较大小(递归解法)

    万次阅读 2018-03-06 13:03:42
    下面说一下我的解题思路:首先这题目就是简单的最值问题。这问题一般的话有两思路:1、定义一个数为最值,然后与其余的进行比较然后比较,找出最值。 2、对所有的进行排序,然后从排序好的里面就可以...
  • 分析1:对于给定数组找出其中最大的两个数,很容易想到的就是遍历数组。首先遍历整个数组,找出最大的一元素并记录下该位置;然后分别遍历该位置之前的区间和该位置之后的区间,分别找出这两子区间的最大值,...
  • C++第7周任务2-四数中最大

    千次阅读 2012-10-11 16:06:52
    项目2:输入4整数,输出其中的最大值。 要求:程序调试成功后,提交漂亮、规范的博文作为报告(参考上一任务的模板自行改造) 项目2扩展一(选做):输入4整数,输出其中的最大值和最小值。 项目2扩展二(选...
  • python之输入一系列整数输出最大

    千次阅读 2020-12-05 15:15:05
    在python学习,我们经常会遇到:编写一程序,输入若干整数或者是在一串字符,输出最大值()的问题。那么在这里,我给出了几种常见的,也是几种比较常用的方法,希望能给大家的学习带来一定的帮助。第一种:...
  • Java线程池的核心线程最大线程

    万次阅读 多人点赞 2021-03-14 19:24:35
    整个过程就像下面有趣的动画: 下面我们先来了解一下Java线程池的参数。 希望看完这篇文章后, 再提起线程池的时候, 你脑海首先出现的, 会是一花瓶 : ) 1线程池的参数意义 Java线程池的构造函数如下: ...
  • Java数字的舍五入和取整

    千次阅读 2020-06-18 17:31:15
    Java对数字进行舍五入或取整处理经常使用Math库的三方法: ceil floor round 1 ceil 向上取整 ceil英文释义:天花板。天花板在上面,所以是向上取整,好记了。 Math.ceil 函数接收一double类型的参数...
  • 写一函数,使给定的一二维数组3*4进行行列转置,即行列互换,并输出转置前后的结果.#include"stdio.h"voidmain(){inta[3][4]={{1,2,3,4},{5,6,7,8},{9,0,1,2}};intb[4][3];inti,j;printf("bef输入一M行M列的二维...
  • 这道题目是坑啊,我上来都没看直接当做之前一篇博文求解矩阵中最大子数组和的问题了,采用动态规划的思想来解决,结果呢,只通过了10%左右,感觉很不可思议,于是重新读题发现不对了,人家说的是三数字的乘积...
  • 再解释下什么叫能分解成两两位相乘,例如9999肯定是最大位回文,但是很明显不能分解成两两位相乘的形式,所以不符合要求,像9009,他是回文,而且9009=91*99,所以符合要求。 下面是代码 #include...
  • 先拿10000个数建堆,然后一次添加剩余元素,如果大于堆顶的(10000最小的),将这个数替换堆顶,并调整结构使之仍然是一最小堆,这样,遍历完后,堆的10000个数就是所需的最大的10000。建堆...
  • Java最大值的4种方法实例代码

    千次阅读 2021-02-25 18:53:46
    前言本文主要给大家分享了关于java求最大值的4方法,文中给出了完整的示例代码,下面话不多少了,来一起看看吧示例代码:/***@author Prannt*求最大值(或最小值)*本例以int数据类型为例,可指定其他数据类型*///...
  • 求各位数字组成的最大数

    千次阅读 2020-03-29 21:15:28
    2020年04月20日 星期一 23:00 允许迟交 否 关闭时间 2020年04月30日 星期 23:00 任意输入一自然数(不大于99999999),输出该自然数的各位数字组成的最大数。例如,输入 1593 ,则输出为 9531 。 输入: 自然数 n...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 766,718
精华内容 306,687
关键字:

下面四个数中最大的是