大数据基础部分面试题:
一.你了解Hadoop吗?讲一下Hadoop中HDFS的读写原理。
读:
客户端调用FileSystem的open方法,来打开但愿读取的文件。
FileSystem经过Rpc与namenode通讯,namenode将获取到的信息整理,并将文件的全部内容发送给FileSystem对象,全部的副本块都会有对应的datanode位置信息;namenode会根据当前的全部节点状态判断最佳datanode位置,而且将此datanode的位置信息封装到传送的信息中。
客户端经过FileSystem返回的流对象,调用read方法,开始读取文件的数据,若是一个文件很是大,数据块数量庞大,namenode不会一次性返回全部的块信息,而是一批一批的返回,而且从第一批开始逐次读取。
对于客户端来说,读取数据的操做是不透明的,用户并不须要关心底层流在数据块之间的跳转,或者读取失败后的流跳转,底层流对象会从第一个数据块开始,直接调用当前的FileSystem返回的流对象的read方法进行连续读取。
按照顺序每当读完一个数据块,底层流会跳转到下一个数据块读取。
当全部的数据块读取完毕,用户调用FSDataInputStream的close方法进行关流便可。java
写:node
二.Mapreduce 的Shuffle过程
在 Map 端的运做
Map function 的运行方式就是从 RecordReader 那边读出一个 input key value pair, 处理,而后把处理结果(一般也是 key value pair 形式)写到一个Hadoop maintained memory buffer 里,而后读取下一个 input key value pair.linux
Hadoop maintained memory buffer 里的 key value pair 按 key 值排序,而且按照 reduce partition 分到不一样 partition 里(这就是 partitioner 被调用的时候)。一旦 memory buffer 满了,就会被 Hadoop 写到 file 里,这个过程叫 spill, 写出的 file 叫 spill file.面试
注意,这些 spill file 存在 map 所在 host 的 local disk 上,而不是咱们以前介绍过的 HDFS.算法
随着 Map 不断运行,有可能有多个 spill file 被制造出来。当 Map 结束时,这些 spill file 会被 merge 起来——不是 merge 成一个 file,而是按 reduce partition 分红多个。sql
在 Reduce 端的运做:
因为 Map tasks 有可能在不一样时间结束,因此 reduce tasks 不必等全部 map tasks 都结束才开始。事实上,每一个 reduce task 有一些 threads 专门负责从 map host copy map output(默认是5个,能够经过 $mapred.reduce.parallel.copies 参数设置);考虑到网络的延迟问题,并行处理能够在必定程度上提升效率。数据库
经过前面的学习,咱们知道 Hadoop JobTracker 会根据输入数据位置安排 map tasks,但 reduce tasks 是不知道这种安排的。那么当 reduce task 须要从map host copy map output 时,它怎么知道 map host 的位置呢(URL/IP)?编程
其实当 Map tasks 成功结束时,他们会通知负责的 tasktracker, 而后消息经过 jobtracker 的 heartbeat 传给 jobtracker. 这样,对于每个 job, jobtracker 知道 map output 和 map tasks 的关联。Reducer 内部有一个 thread 负责按期向 jobtracker 询问 map output 的位置,直到 reducer 获得全部它须要处理的 map output 的位置。缓存
Reducer 的另外一个 thread 会把拷贝过来的 map output file merge 成更大的 file. 若是 map task 被 configure 成须要对 map output 进行压缩,那 reduce 还要对 map 结果进行解压缩。当一个 reduce task 全部的 map output 都被拷贝到一个它的 host上时,reduce 就要开始对他们排序了。安全
排序并非一次把全部 file 都排序,而是分几轮。每轮事后产生一个结果,而后再对结果排序。最后一轮就不用产生排序结果了,而是直接向 reduce 提供输入。这时,用户提供的 reduce function 就能够被调用了。输入就是 map task 产生的 key value pairs.
三.NIO和IO的区别
NIO vs IO之间的理念上面的区别(NIO将阻塞交给了后台线程执行)
IO是面向流的,NIO是面向缓冲区的
Java IO面向流意味着每次从流中读一个或多个字节,直至读取全部字节,它们没有被缓存在任何地方;
NIO则能先后移动流中的数据,由于是面向缓冲区的
IO流是阻塞的,NIO流是不阻塞的
Java IO的各类流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据彻底写入。该线程在此期间不能再干任何事情了
Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,可是它仅能获得目前可用的数据,若是目前没有数据可用时,就什么都不会获取。NIO可以让您只使用一个(或几个)单线程管理多个通道(网络链接或文件),但付出的代价是解析数据可能会比从一个阻塞流中读取数据更复杂。
非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不须要等待它彻底写入,这个线程同时能够去作别的事情。
选择器
Java NIO的选择器容许一个单独的线程来监视多个输入通道,你能够注册多个通道使用一个选择器,而后使用一个单独的线程来“选择”通道:这些通道里已经有能够处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
四.Kfaka中topic和partition的关系是什么,如何理解?
topic在逻辑上能够被认为是一个queue。每条消费都必须指定它的topic,能够简单理解为必须指明把这条消息放进哪一个queue里。为了使得 Kafka的吞吐率能够水平扩展,物理上把topic分红一个或多个partition,每一个partition在物理上对应一个文件夹,该文件夹下存储 这个partition的全部消息和索引文件。partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。
五.Mapreduce的shuffle过程
当MAP函数开始产生输出时,不是直接将文件写入到磁盘中,而是先将数据写入到缓存中,并对数据进行一系列的优化操做,以减小数据传输的量,并减小REDUCE端的操做。
首先每一个MAP会有一个100MB大小的缓冲区,数据从MAP函数输出时会先进入到缓冲区,当到达缓冲区的阈值(80%)时,一个后台线程开始把数据SPILL(溢出)到磁盘中,此时数据仍然会不断的写入到缓存中,若缓冲区已满,数据会阻塞等待数据从缓冲区写入磁盘,当缓冲区有剩余大小时,才继续写入到缓冲区。
在写入磁盘前,数据会根据REDUCE的数量并按照MAP函数输出的KEY值进行PARTITION分区,这样作的好处是能够将KEY值相同的数据最终汇聚到同一个REDUCE任务中,提升效率。在每一个分区中,后台线程会对数据也按照KEY值进行排序,而且在排序后若存在COMBINER合并任务,会将数据按照合并的要求进行合并,其实COMBINER的过程也就是一个小型的REDUCER,这样作的好处是减小REDUCE端的操做。在讲数据写入磁盘的过程当中对数据进行压缩,也是一个很好的选择,能够加快磁盘写入的效率,而且节约磁盘空间,从而减小传输到REDUCE任务端的数据量。
在REDUCE端会经过心跳机制向jobTracker来获取已经执行完毕的MAP任务,经过HTTP的方式来得到分区文件信息,REDUCE默认存在5个复制线程来对分区中的文件进行复制,在REDUCE端也会村在一个缓冲区,来处理复制过来的文件,若缓冲区一样达到阈值,会将处理的文件写入磁盘,在缓冲区处理文件时,若在MAP阶段对数据进行了压缩操做,在REDUCE端须要对数据进行解压缩才能够处理。最后数据就会进入REDUCE函数进行合并。最终输出到HDFS文件系统中。
六.Hadoop的调度机制
1.先入先出FIFO
Hadoop 中默认的调度器,它先按照做业的优先级高低,再按照到达时间的前后选择被执行的做业。
2.公平调度器(至关于时间片轮转调度)
为任务分配资源的方法,其目的是随着时间的推移,让提交的做业获取等量的集群共享资源,让用户公平地共享集群。具体作法是:当集群上只有一个任务在运行时,它将使用整个集群,当有其余做业提交时,系统会将TaskTracker节点空间的时间片分配给这些新的做业,并保证每一个任务都获得大概等量的CPU时间。
配置公平调度器
3.容量调度器
支持多个队列,每一个队列可配置必定的资源量,每一个队列采用 FIFO 调度策略,为 了防止同一个用户的做业独占队列中的资源,该调度器会对同一用户提交的做业所占资源量进行限定。调度时,首先按如下策略选择一个合适队列:计算每一个队列中正在运行的任务数与其应该分得的计算资源之间的比值,选择一个该比值最小的队列;而后按如下策略选择该队列中一个做业:按照做业优先级和提交时间顺序选择 ,同时考虑用户资源量限制和内存限制。可是不可剥夺式。
七.Hive中内部表与外部表的区别:
Hive 建立内部表时,会将数据移动到数据仓库指向的路径;若建立外部表,仅记录数据所在的路径,不对数据的位置作任何改变。在删除表的时候,内部表的元数据和数据会被一块儿删除,而外部表只删除元数据,不删除数据。这样外部表相对来讲更加安全些,数据组织也更加灵活,方便共享源数据。
八.Hadoop的二次排序
第一种方法是,Reducer将给定key的全部值都缓存起来,而后对它们再作一个Reducer内排序。可是,因为Reducer须要保存给定key的全部值,可能会致使出现内存耗尽的错误。
第二种方法是,将值的一部分或整个值加入原始key,生成一个组合key。这两种方法各有优点,第一种方法编写简单,但并发度小,数据量大的状况下速度慢(有内存耗尽的危险),
第二种方法则是将排序的任务交给MapReduce框架shuffle,更符合Hadoop/Reduce的设计思想。咱们将编写一个Partitioner,确保拥有相同key(原始key,不包括添加的部分)的全部数据被发往同一个Reducer,还将编写一个Comparator,以便数据到达Reducer后即按原始key分组。
九.全部的hive任务都会有reducer的执行吗?
答:不是,因为当前hive的优化,使得通常简单的任务不会去用reducer任务;只有稍微复杂的任务才会有reducer任务
举例:使用select * from person ; 就不会有reducer
十.hive表关联查询,如何解决数据倾斜的问题?
倾斜缘由:
map输出数据按key Hash的分配到reduce中,因为key分布不均匀、业务数据自己的特、建表时考虑不周、等缘由形成的reduce 上的数据量差别过大。
1)、key分布不均匀;
2)、业务数据自己的特性;
3)、建表时考虑不周;
4)、某些SQL语句自己就有数据倾斜;
如何避免:对于key为空产生的数据倾斜,能够对其赋予一个随机值。
解决方案
1>.参数调节:
hive.map.aggr = true
hive.groupby.skewindata=true
有数据倾斜的时候进行负载均衡,当选项设定位true,生成的查询计划会有两个MR Job。第一个MR Job中,Map的输出结果集合会随机分布到Reduce中,每一个Reduce作部分聚合操做,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不一样的Reduce中,从而达到负载均衡的目的;第二个MR Job再根据预处理的数据结果按照Group By Key 分布到 Reduce 中(这个过程能够保证相同的 Group By Key 被分布到同一个Reduce中),最后完成最终的聚合操做。
2>.SQL 语句调节:
1)、选用join key分布最均匀的表做为驱动表。作好列裁剪和filter操做,以达到两表作join 的时候,数据量相对变小的效果。
2)、大小表Join:
使用map join让小的维度表(1000 条如下的记录条数)先进内存。在map端完成reduce.
4)、大表Join大表:
把空值的key变成一个字符串加上随机数,把倾斜的数据分到不一样的reduce上,因为null 值关联不上,处理后并不影响最终结果。
5)、count distinct大量相同特殊值:
count distinct 时,将值为空的状况单独处理,若是是计算count distinct,能够不用处理,直接过滤,在最后结果中加1。若是还有其余计算,须要进行group by,能够先将值为空的记录单独处理,再和其余计算结果进行union。
十一. 请谈一下hive的特色是什么?
hive是基于Hadoop的一个数据仓库工具,能够将结构化的数据文件映射为一张数据库表,并提供完整的sql查询功能,能够将sql语句转换为MapReduce任务进行运行。其优势是学习成本低,能够经过类SQL语句快速实现简单的MapReduce统计,没必要开发专门的MapReduce应用,十分适合数据仓库的统计分析。
十二. Kafka主要特色:
因为Spark1.6.0的统一内存管理模型,若算法的数据量大,而计算逻辑较为简单,能够增大内存管理中cache块的比例(默认70%(我也一会儿想不起来,感受这个附近)),若是是数据量小而算法逻辑复杂,能够适当减小cache快的比例;
若是因对是集群CPU资源过度盈余,能够采用增长core的数目,可是core的数目增长到必定程度后,依旧没法彻底利用CPU的计算资源,能够选择增长Executor的数目,一般环境下,一个Executor推荐设置5个Core的个数,超过5个推荐增长Executor的个数
十四.用mapreduce如何处理数据倾斜问题
数据倾泻产生缘由:其次在reduce端默认的分区方式为按照map函数输出key的哈希值,根据哈希值将数据散列在Reduce中,这尽在数据分布比较均衡的状况下比较适用。
首先在MAP函数中增长记录数据倾斜的日志信息,能够经过代码实现,当某个key值超过预先设定的范围就打印该key值的日志
自定义分区方法,能够对原始数据进行抽样的结果来预设定分区的边界,totalOrderPartitioner中的范围分区器能够经过预设的分区值进行分区。另外一个自定义分区方法是根据数据输出键的背景知识来自定义分区,假如map输出的键值来自于一本书,其中大部分则确定是省略词,那么就能够自定义分区将这部分省略次分区到一个REDUCE中,将剩下的键值保存在其余的REDUCE中
执行两次MR的过程,第一次不按照KEY值进行分区,打散数据到REDUCE端,在进行一次MR的操做,此次按照KEY值分区,能够有效的减小数据倾斜的问题。
十五. 列举你知道的经常使用的hadoop管理和监控的命令
-ls -cat -text -cp -put -chmod -chown
-du -get -copyFromLocal -copyToLocal -mv -rm - tail -chgrp
十六. 在mr环节中,那些环节须要优化,如何优化,请详细说明。
一、 setNumReduceTasks 适当的设置reduce的数量,若是数据量比较大,那么能够增长reduce的数量
二、适当的时候使用 combine 函数,减小网络传输数据量 三、压缩map和reduce的输出数据
四、使用SequenceFile二进制文件。
五、经过application 的ui页面观察job的运行参数
六、太多小文件,形成map任务过多的问题,应该能够先合并小文件,或者有一个特定的map做为处理小文件的输入
七、map端效率低缘由分析
源文件的大小远小于HDFS的块的大小。这意味着任务的开启和中止要耗费更多的时间,就没有足够的时间来读取并处理输入数据。
源文件没法分块。这致使须要经过网络IO从其余节点读取文件块。
一个节点的本地磁盘或磁盘控制器运行在降级模式中,读取写入性能都不好。这会影响某个节点,而不是所有节点。
源文件不来自于HDFS。则多是Hadoop节点和数据源之间的延迟致使了性能低下。
Map任务从其余数据节点读取数据。能够从JobTracker的map任务细节信息和任务运行尝试中找到输入块的位置。若是输入块的位置不是任务执行的节点,那就不是本地数据了。
十七. 如何用MAPREDUCE实现两张表的链接
方案一:Reduce side join。在Map阶段读取两张表F1,F2,分别对读取的KEY VALUE进行TAG标签,而后输入到REDUCE端,REDUCE端获得数据后按照相同KEY值,对不一样标签的相同KEY值进行JOIN。
方案二:因为在REDUCE端进行JOIN效率十分低,由于在MAP端有大量的数据进行SHUFFLE到REDUCE端。因此在如下状况下咱们能够考虑在MAP端进行JOIN,若两张表中有一张表比较少,甚至能够放到内存中,那么咱们能够利用HADOOP的中DISTRIBUTEDCATCH.ADDCATCHFILE()将文件加载到缓存中,他的参数是URL,在JOBTRACKER加载任务时,会将这个URL下的文件拷贝到各个TASKTRACKER上,并经过DISTRIBUTEDCATCH.GETLOCALCATCHFILE()获取这个文件,从而进行JOIN操做。
十八. fsimage和edit的区别?
Fsimage是在namenode节点中保存了文件系统全部的目录、文件信息,文件信息中包含数据块描述信息,修改时间,访问时间等。对于目录来讲包括修改时间,访问权限信息。edit保存的是当对hdfs进行增删改时记录的操做,在HADOOP中存在secoundNamenode节点,当namenode中的小文件太多时,将两个文件发送到secoundNamenode中进行和并,并发送会Namenode来保证当前hdfs中信息的完整。
十九. synchronized和lock的区别
synchronized:在须要同步的对象中加入此控制,synchronized能够加在方法上,也能够加在特定代码块中,括号中表示须要锁的对象。
lock:须要显示指定起始位置和终止位置。通常使用ReentrantLock类作为锁,多个线程中必需要使用一个ReentrantLock类作为对象才能保证锁的生效。且在加锁和解锁处须要经过lock()和unlock()显示指出。因此通常会在finally块中写unlock()以防死锁。
二十. 给40亿个不重复的unsigned int的整数,没排过序的,而后再给一个数,如何快速判断这个数是否在那40亿个数当中?
这个问题在《编程珠玑》里有很好的描述,你们能够参考下面的思路,探讨一下:
又由于2^32为40亿多,因此给定一个数可能在,也可能不在其中;
这里咱们把40亿个数中的每个用32位的二进制来表示
假设这40亿个数开始放在一个文件中。
而后将这40亿个数分红两类:
1.最高位为0
2.最高位为1
并将这两类分别写入到两个文件中,其中一个文件中数的个数<=20亿,而另外一个>=20亿(这至关于折半了);
与要查找的数的最高位比较并接着进入相应的文件再查找
再而后把这个文件为又分红两类:
1.次最高位为0
2.次最高位为1
并将这两类分别写入到两个文件中,其中一个文件中数的个数<=10亿,而另外一个>=10亿(这至关于折半了);
与要查找的数的次最高位比较并接着进入相应的文件再查找。
二十一. HDFS存储大量的小文件会有什么问题,如何解决?
(1)HDFS不适合大量小文件的存储,因namenode将文件系统的元数据存放在内存中,所以存储的文件数目受限于 namenode的内存大小。HDFS中每一个文件、目录、数据块占用150Bytes。若是存放的文件数目过多的话会占用很大的内存
(2)HDFS适用于高吞吐量,而不适合低时间延迟的访问。若是同时存入大量的小文件会花费很长的时间
(3) 流式读取的方式,不适合多用户写入,以及任意位置写入。若是访问小文件,则必须从一个datanode跳转到另一个datanode,这样大大下降了读取性能。
二十二.Hbase的表设计原则
HBase表的设计 主要是 列族的设计 和 行键的设计
1.列族的设计 在设计hbase表时候,列族不宜过多,越少越好,官方推荐hbase表的列族不宜超过3个。 常常要在一块儿查询的数据最好放在一个列族中,尽可能的减小跨列族的数据访问。 若是有多个列族 多个列族中的数据应该设计的比较均匀 2.行键的设计 hbase表中行键是惟一标识一个表中行的字段,因此行键设计的好很差将会直接影响将来对hbase的查询的性能和查询的便利性 因此hbase中的行键是须要进行设计的 行键设计的基本原则: 行键必须惟一 必须惟一才能惟一标识数据 行键必须有意义 这样才能方便数据的查询 行键最好是字符串类型 由于数值类型在不一样的系统中处理的方式可能不一样 行键最好具备固定的长度 不一样长度的数据可能会形成天然排序时排序的结果和预期不一致 行键不宜过长 行键最多能够达到64KB,可是最好是在10~100字节之间,最好不要超过16字节,越短越好,最好是8字节的整数倍。 行键的最佳实践: 散列原则: 行键的设计将会影响数据在hbase表中的排序方式,这会影响region切分后的结果,要注意,在设计行键时应该让常常要查询的数据分散在不一样的region中,防止某一个或某几个regionserver成为热点。 有序原则: 行键的设计将会影响数据在hbase表中的排序方式,因此一种策略是将常常连续查询的条件做为行键最前面的数据,这样一来能够方便批量查询
二十三.Hadoop的压缩算法
Hadoop 对于压缩格式的是自动识别。若是咱们压缩的文件有相应压缩格式的扩展名(好比 lzo,gz,bzip2 等)。
Hadoop 会根据压缩格式的扩展名自动选择相对应的解码器来解压数据,此过程彻底是 Hadoop 自动处理,咱们只须要确保输入的压缩文件有扩展名。
Hadoop 对每一个压缩格式的支持, 详细见下表:
压缩格式 工具 算法 扩展名 多文件 可分割性
DEFLATE 无 DEFLATE .deflate 不 不
GZIP gzip DEFLATE .gzp 不 不
ZIP zip DEFLATE .zip 是 是,在文件范围内
BZIP2 bzip2 BZIP2 .bz2 不 是
LZO lzop LZO .lzo 不 是
若是压缩的文件没有扩展名,则须要在执行 MapReduce 任务的时候指定输入格式。
1) Bzip2 压缩效果明显是最好的,可是 bzip2 压缩速度慢,可分割。
2) Gzip 压缩效果不如 Bzip2,可是压缩解压速度快,不支持分割。
3) LZO 压缩效果不如 Bzip2 和 Gzip,可是压缩解压速度最快!而且支持分割!
1.gzip压缩
优势:
压缩率比较高,并且压缩/解压速度也比较快;
hadoop自己支持,在应用中处理gzip格式的文件就和直接处理文本同样;
有hadoop native库;
大部分linux系统都自带gzip命令,使用方便。
缺点:不支持split。
应用场景:
当每一个文件压缩以后在130M之内的(1个块大小内),均可以考虑用gzip压缩格式。譬如说一天或者一个小时的日志压缩成一个gzip文件,运行mapreduce程序的时候经过多个gzip文件达到并发。
hive程序,streaming程序,和java写的mapreduce程序彻底和文本处理同样,压缩以后原来的程序不须要作任何修改。
2.lzo压缩
优势:
压缩/解压速度也比较快,合理的压缩率;
支持split,是hadoop中最流行的压缩格式;
支持hadoop native库;
能够在linux系统下安装lzop命令,使用方便。
缺点:
压缩率比gzip要低一些;
hadoop自己不支持,须要安装;
在应用中对lzo格式的文件须要作一些特殊处理(为了支持split须要建索引,还须要指定inputformat为lzo格式)。
应用场景:
一个很大的文本文件,压缩以后还大于200M以上的能够考虑,并且单个文件越大,lzo优势越明显。
3.snappy压缩
优势:
高速压缩速度和合理的压缩率;
支持hadoop native库。
缺点:
不支持split;
压缩率比gzip要低;
hadoop自己不支持,须要安装;
linux系统下没有对应的命令。
应用场景:
当mapreduce做业的map输出的数据比较大的时候,做为map到reduce的中间数据的压缩格式;
或者做为一个mapreduce做业的输出和另一个mapreduce做业的输入。
4.bzip2压缩
优势:
支持split;
具备很高的压缩率,比gzip压缩率都高;
hadoop自己支持,但不支持native;
在linux系统下自带bzip2命令,使用方便。
缺点:
压缩/解压速度慢;
不支持native。
应用场景:
适合对速度要求不高,但须要较高的压缩率的时候,能够做为mapreduce做业的输出格式;
或者输出以后的数据比较大,处理以后的数据须要压缩存档减小磁盘空间而且之后数据用得比较少的状况;
或者对单个很大的文本文件想压缩减小存储空间,同时又须要支持split,并且兼容以前的应用程序(即应用程序不须要修改)的状况。
二十四.算法思想题
方案2:若是容许有必定的错误率,可使用Bloom filter,4G内存大概能够表示340亿bit。将其中一个文件中的url使用Bloom filter映射为这340亿bit,而后挨个读取另一个文件的url,检查是否与Bloom filter,若是是,那么该url应该是共同的url(注意会有必定的错误率)。
二十五.算法思想题二
有10个文件,每一个文件1G,每一个文件的每一行存放的都是用户的query,每一个文件的query均可能重复。要求你按照query的频度排序。
方案1:
s 顺序读取10个文件,按照hash(query)%10的结果将query写入到另外10个文件(记为)中。这样新生成的文件每一个的大小大约也1G(假设hash函数是随机的)。
s 找一台内存在2G左右的机器,依次对用hash_map(query, query_count)来统计每一个query出现的次数。利用快速/堆/归并排序按照出现次数进行排序。将排序好的query和对应的query_cout输出到文件中。这样获得了10个排好序的文件(记为)。
s 对这10个文件进行归并排序(内排序与外排序相结合)。
方案2:
通常query的总量是有限的,只是重复的次数比较多而已,可能对于全部的query,一次性就能够加入到内存了。这样,咱们就能够采用trie树/hash_map等直接来统计每一个query出现的次数,而后按出现次数作快速/堆/归并排序就能够了。
方案3:
与方案1相似,但在作完hash,分红多个文件后,能够交给多个文件来处理,采用分布式的架构来处理(好比MapReduce),最后再进行合并。
二十六.算法思想题三
有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。
方案1:顺序读文件中,对于每一个词x,取,而后按照该值存到5000个小文件(记为)中。这样每一个文件大概是200k左右。若是其中的有的文件超过了1M大小,还能够按照相似的方法继续往下分,知道分解获得的小文件的大小都不超过1M。对每一个小文件,统计每一个文件中出现的词以及相应的频率(能够采用trie树/hash_map等),并取出出现频率最大的100个词(能够用含100个结点的最小堆),并把100词及相应的频率存入文件,这样又获得了5000个文件。下一步就是把这5000个文件进行归并(相似与归并排序)的过程了。
二十七.算法思想题四
一共有N个机器,每一个机器上有N个数。每一个机器最多存O(N)个数并对它们操做。如何找到个数中的中数?
方案1:先大致估计一下这些数的范围,好比这里假设这些数都是32位无符号整数(共有个)。咱们把0到的整数划分为N个范围段,每一个段包含个整数。好比,第一个段位0到,第二段为到,…,第N个段为到。而后,扫描每一个机器上的N个数,把属于第一个区段的数放到第一个机器上,属于第二个区段的数放到第二个机器上,…,属于第N个区段的数放到第N个机器上。注意这个过程每一个机器上存储的数应该是O(N)的。下面咱们依次统计每一个机器上数的个数,一次累加,直到找到第k个机器,在该机器上累加的数大于或等于,而在第k-1个机器上的累加数小于,并把这个数记为x。那么咱们要找的中位数在第k个机器中,排在第位。而后咱们对第k个机器的数排序,并找出第个数,即为所求的中位数。复杂度是的。
方案2:先对每台机器上的数进行排序。排好序后,咱们采用归并排序的思想,将这N个机器上的数归并起来获得最终的排序。找到第个即是所求。复杂度是的。
二十八.算法思想题五
将多个集合合并成没有交集的集合:给定一个字符串的集合,格式如:。要求将其中交集不为空的集合合并,要求合并完成的集合之间无交集,例如上例应输出。
(1) 请描述你解决这个问题的思路;
(2) 给出主要的处理流程,算法,以及算法的复杂度;
(3) 请描述可能的改进。
方案1:采用并查集。首先全部的字符串都在单独的并查集中。而后依扫描每一个集合,顺序合并将两个相邻元素合并。例如,对于,首先查看aaa和bbb是否在同一个并查集中,若是不在,那么把它们所在的并查集合并,而后再看bbb和ccc是否在同一个并查集中,若是不在,那么也把它们所在的并查集合并。接下来再扫描其余的集合,当全部的集合都扫描完了,并查集表明的集合即是所求。复杂度应该是O(NlgN)的。改进的话,首先能够记录每一个节点的根结点,改进查询。合并的时候,能够把大的和小的进行合,这样也减小复杂度。
二十九.Hive UDF编写错误从哪方面调错?
首先查日志,UDF的日志是保存在Hadoop MR的日志文件中,
其次经过错误提示经过管道符grep |查找问题所在,并针对问题进行改进
在日志文件过大的状况下,能够经过head tail sed 等指令进行分段查找
三十.什么是tire树?
Trie树,又称单词查找树、字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构。典型应用是用于统计和排序大量的字符串(但不只限于字符串),因此常常被搜索引擎系统用于文本词频统计。它的优势是:最大限度地减小无谓的字符串比较,查询效率比哈希表高。
Trie的核心思想是空间换时间。利用字符串的公共前缀来下降查询时间的开销以达到提升效率的目的。
Trie树也有它的缺点,Trie树的内存消耗很是大.固然,或许用左儿子右兄弟的方法建树的话,可能会好点.
三点特征:
1)根节点不包含字符,除根节点外每个节点都只包含一个字符。
2)从根节点到某一节点,路径上通过的字符链接起来,为该节点对应的字符串。
3)每一个节点的全部子节点包含的字符都不相同。
三十一. 500桶酒,其中1桶是毒酒;48小时后要举行酒会;毒酒喝下去会在以后的第23-24小时内毒死人;国王决定用囚犯来试酒,不介意囚犯死多少,只要求用最少的囚犯来测试出哪一桶是毒酒,问最少须要多少囚犯才能保证找出毒酒?请诸位自序们为乌有国王出个主意!
思路一
须要9我的
将500桶毒酒进行编号,并用二进制表示.获得000000000~111110100.
每一个囚犯对应二进制的每一位,而后喝下对应位数为1的那个编号的毒酒
而后根据死亡的囚犯编号或者毒酒的二进制编码.
进而得到毒酒的编号.
如毒酒编号为350,那么二进制对应为101011110.难么囚犯234579会死亡.
思路二
须要两我的,由于23*23=529>500
将毒酒进行编号,而且每23桶做为一组,1~23;24~46…..
囚犯一每小时喝下每一组酒
囚犯二每小时喝下每一组中对应的酒,如第一小时喝下每组的第一桶酒.第二小时喝下每一组对应的第二桶酒.
而后根据死亡时间进行交叉查找
根据2人死亡计时和行、列交叉点便可找到那桶毒酒了。
如囚犯一34小时死亡,表明(34-23)组酒有毒,即231~253有毒.
囚犯二38小时死亡,表明每组的(38-23)号=15号有问题.
综合后即为231+15-1=245号酒有问题.
简单地说把500桶分红23行22列: 第一个囚犯每小时喝一行; 第二个囚犯每小时喝一列。 根据2人死亡计时和行、列交叉点便可找到那桶毒酒了。