美文网首页
程序员面试修炼13 | BAT面试必考算法题

程序员面试修炼13 | BAT面试必考算法题

作者: 淇奥qiaoqiao | 来源:发表于2018-05-22 18:09 被阅读0次

很多创业者想轻轻松松成功,如果你想过很舒服的日子,最好不要创业。可以找一个大公司,收入比较稳定,过着非常体面的生活,就挺好的。 ——雷军

image

数据分析常用指标/术语

平均数:我们日常生活、工作中常说的平均数一般都指算术平均数。算术平均数指将一组数据通过累加求和,再除以参与求和的数据的个数,所获得的这一组数据的平均值。算术平均数在统计分析中具有重要的指标意义,通过平均数可以对比组内其他数据的沉浮、高低情况等。

绝对数:绝对数是反应客观现象总体在一定时间、一定地点条件下的总规模、总水平的综合性指标,也是数据分析中常用的指标。比如年GDP,总人口,又如成都有70万考生,成都信息工程大学有2万师生等等。

相对数:相对数是指两个有联系的指标计算而得出的数值,它是反应客观现象之间的数量联系紧密程度的综合指标。

相对数的计算公式:相对数 = 比较值(笔数)/基础值(基数)

相对数一般以倍数、百分数等表示,它反应客观香香之间数量的联系程度。

百分比:百分比是相对数中的一种,他表示一个数是另一个数的百分之几,也成为百分率或百分数。百分比的分母是100,也就是用1%作为度量单位,因此便于比较。

百分点:百分点是指不同时期以百分数的形式表示的相对指标的变动幅度,1%等于1个百分点。比如,某公司发言,我公司今年第一季度的收入比上个季度提升了13个百分点。百分比一般与“提高了”、“上升/下降”等词搭配使用。

频数:一个数据在整体中出现的次数。某如某班学生成绩中,88分的有5个,则5为频数。反映了一个数据在整体样本中出现的次数。

频率:反应一个数据在样本中出现的频繁程度,是数据的频数除以样本总量得到的。

比例:比例是指在总体中各数据占总体的比重,通常反映总体的构成和比例,即部分与整体之间的关系。比如某班男20,女30人,则男生的比例是2/5,女生是3/5。比例的基数(分母)是同一个基数。

比率:比率是指总体中某些数据之间的比值。反映了整体中部分与部分之间的关系。以上述例子为例,男女比率为2:3.

倍数:表示一个数据是两个数据的几倍,通常用一个数据除以另一个数据获得,倍数一般用来表示上升、增长幅度,一般不表示减少幅度。

番数:指原来数量的2的n次方。比如今年利润比去年翻一番,意思就是今年利润是去年2倍(2的1次方),今年利润比去年翻两番,就是今年利润是去年的4倍(2的2次方)。所以,翻番可比倍数猛的多。

同比:指的是与历史同时期的数据相比较而获得的比值,反应事物发展的相对性。比如,我公司今年第一季度出海产量同比增长45%,意思就是今年第一季度的出海产量比去年第一季度的出海产量增加了45%,这就是同比。

环比:指与上一个统计时期的值进行对比获得的值,主要反映事物的逐期发展的情况。例如我公司今年第一季度出海产量环比增长22%,表示我公司今年第一季度的出海产量比去年第四季度(去年最后一个季度)出海产量增长了22%。

通俗简化的讲,同比=2015年5月 / 2014年5月,环比=2015年5月/2015年4月。

image

笔试/面试真题真题

题目描述

1、假设淘宝一天有5亿条成交数据,求出销量最高的100个商品并给出算法的时间复杂度。

解题思路:

先用哈希,统计每个商品的成交次数,然后再用在N个数中找出前K大个数的方法找出成交次数最多的前100个商品。

优化方法:可以把5亿个数据分组存放,比如放在5000个文件中。这样就可以分别在每个文件的10^6个数据中,用哈希+堆统计每个区域内前100个频率最高的商品,最后求出所有记录中出现频率最高的前100个商品。

题目描述

2、有10亿个杂乱无章的数,怎样最快地求出其中前1000大的数。

解题思路:

方法一: 建一个1000个数的最小堆,然后依次添加剩余元素,如果大于堆顶的数(堆中最小的),将这个数替换堆顶,并调整结构使之仍然是一个最小堆,这样,遍历完后,堆中的1000个数就是所需的最大的1000个。

算法的时间复杂度为O(nlogk)=n*log1000=10n(n为10亿,k为1000)。

优化的方法1:分治法。可以把所有10亿个数据分组存放,比如分别放在1000个文件中。这样处理就可以分别在每个文件的10^6个数据中找出最大的10000个数,合并到一起再找出最终的结果。

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

方法二

1.用每一个BIT标识一个整数的存在与否,这样一个字节可以标识8个整数的存在与否,对于所有32位的整数,需要512Mb,所以开辟一个512Mb的字符数组A,初始全0 。

2.依次读取每个数n,对于数n,n存放在A[N>>3]中的某个bit,因此,将A[n>>3]设置为A[n>>3]|(1<<(n%8))(这里是1左移几位),相当于将每个数的对应位设置为1 。

3.在A中,从数组尾开始向前遍历,从大到小读取1000个值为1的数,就是最大的1000个数了。

这样读文件就只需要1遍,在不考虑内存开销的情况下,应该是速度最快的方法了。

题目描述

3、给一列无序数组,求出中位数并给出算法的时间复杂度。

解题思路:

若数组有奇数个元素,中位数是a[(n-1)/2];若数组有偶数个元素,中位数为a[n/2-1]和a[n/2]两个数的平均值。这里为方便起见,假设数组为奇数个元素。

思路一:把无序数组排好序,取出中间的元素。时间复杂度取决于排序算法,最快是快速排序,O(nlogn),或者是非比较的基数排序,时间为O(n),空间为O(n)。这明显不是我们想要的。

思路二:采用快速排序的分治partition过程。任意挑一个元素,以该元素为支点,将数组分成两部分,左边是小于等于支点的,右边是大于支点的。如果左侧长度正好是(n-1)/2,那么支点恰为中位数。如果左侧长度<(n-1)/2, 那么中位数在右侧,反之,中位数在左侧。 进入相应的一侧继续寻找中位数。

下面来看****解题代码(如果代码页面超出可以左右上下移动):

//快速排序的分治过程找无序数组的中位数 

int partition(int a[], int low, int high)//快排的一次排序过程 

{ 

   int q = a[low]; 

   while (low < high) 

   { 

       while (low < high && a[high] >= q) 

           high--; 

       a[low] = a[high]; 

       while (low < high && a[low] <= q) 

           low++; 

       a[high] = a[low]; 

   } 

   a[low] = q; 

   return low; 

} 

int findMidium(int a[], int n) 

{ 

   int index = n / 2; 

   int left = 0; 

   int right = n - 1; 

   int q = -1; 

   while (index != q) 

   { 

       q = partition(a, left, right); 

       if (q < index) 

           left = q + 1; 

       else if (q>index) 

           right = q - 1; 

   } 

   return a[index]; 

}  

思路三:将数组的前(n+1)/2个元素建立一个最小堆。然后,对于下一个元素,和堆顶的元素比较,如果小于等于,丢弃之,如果大于,则用该元素取代堆顶,再调整堆,接着看下一个元素。重复这个步骤,直到数组为空。当数组都遍历完了,(堆中元素为最大的(n+1)/2个元素,)堆顶的元素即是中位数。

下面来看****解题代码(如果代码页面超出可以左右上下移动):

//构建最小堆找无序数组的中位数 

void nswap(int& i, int& j) 

{ 

    i= i^j; 

    j= i^j; 

    i= i^j; 

} 

void minHeapify(int a[], int i, intlen) 

{ 

   int temp; 

   int least = i; 

   int l = i * 2 + 1; 

   int r = i * 2 + 2; 

   if (l < len && a[l] < a[least]) 

       least = l; 

   if (r < len && a[r] < a[least]) 

       least = r; 

   if (least != i) 

   { 

       nswap(a[i], a[least]); 

       minHeapify(a, least, len); 

   } 

} 

void buildMinHeap(int a[], int len) 

{ 

   for (int i = (len-2) / 2; i >= 0; i--) 

   { 

       minHeapify(a, i, len); 

   } 

} 

int findMidium2(int a[], int n) 

{ 

   buildMinHeap(a, (n + 1) / 2); 

   for (int i = (n + 1) / 2; i < n; i++) 

   { 

       if (a[i] > a[0]) 

       { 

           nswap(a[i], a[0]); 

           minHeapify(a, 0,(n + 1) / 2); 

       }        

   } 

   return a[0]; 

}  

数据分析必须掌握的知识

一. 数据采集

了解数据采集的意义在于真正了解数据的原始面貌,包括数据产生的时间、条件、格式、内容、长度、限制条件等。这会帮助数据分析师更有针对性的控制数据生产和采集过程,避免由于违反数据采集规则导致的数据问题;同时,对数据采集逻辑的认识增加了数据分析师对数据的理解程度,尤其是数据中的异常变化。比如:

► Omniture中的Prop变量长度只有100个字符,在数据采集部署过程中就不能把含有大量中文描述的文字赋值给Prop变量(超过的字符会被截断)。

► 在Webtrekk323之前的Pixel版本,单条信息默认最多只能发送不超过2K的数据。当页面含有过多变量或变量长度有超出限定的情况下,在保持数据收集的需求下,通常的解决方案是采用多个sendinfo方法分条发送;而在325之后的Pixel版本,单条信息默认最多可以发送7K数据量,非常方便的解决了代码部署中单条信息过载的问题。(Webtrekk基于请求量付费,请求量越少,费用越低)。

► 当用户在离线状态下使用APP时,数据由于无法联网而发出,导致正常时间内的数据统计分析延迟。直到该设备下次联网时,数据才能被发出并归入当时的时间。这就产生了不同时间看相同历史时间的数据时会发生数据有出入。

在数据采集阶段,数据分析师需要更多的了解数据生产和采集过程中的异常情况,如此才能更好的追本溯源。另外,这也能很大程度上避免“垃圾数据进导致垃圾数据出”的问题。

二.数据存储

无论数据存储于云端还是本地,数据的存储不只是我们看到的数据库那么简单。比如:

► 数据存储系统是MySql、Oracle、SQLServer还是其他系统。

► 数据仓库结构及各库表如何关联,星型、雪花型还是其他。

► 生产数据库接收数据时是否有一定规则,比如只接收特定类型字段。

► 生产数据库面对异常值如何处理,强制转换、留空还是返回错误。

► 生产数据库及数据仓库系统如何存储数据,名称、含义、类型、长度、精度、是否可为空、是否唯一、字符编码、约束条件规则是什么。

► 接触到的数据是原始数据还是ETL后的数据,ETL规则是什么。

► 数据仓库数据的更新更新机制是什么,全量更新还是增量更新。

► 不同数据库和库表之间的同步规则是什么,哪些因素会造成数据差异,如何处理差异的。

在数据存储阶段,数据分析师需要了解数据存储内部的工作机制和流程,最核心的因素是在原始数据基础上经过哪些加工处理,最后得到了怎样的数据。由于数据在存储阶段是不断动态变化和迭代更新的,其及时性、完整性、有效性、一致性、准确性很多时候由于软硬件、内外部环境问题无法保证,这些都会导致后期数据应用问题。

三.数据提取

数据提取是将数据取出的过程,数据****提取的核心环节是从哪取、何时取、如何取。

► 从哪取,数据来源——不同的数据源得到的数据结果未必一致。

► 何时取,提取时间——不同时间取出来的数据结果未必一致。

► 如何取,提取规则——不同提取规则下的数据结果很难一致。

在数据提取阶段,数据分析师首先需要具备数据提取能力。常用的Select From语句是SQL查询和提取的必备技能,但即使是简单的取数工作也有不同层次。第一层是从单张数据库中按条件提取数据的能力,where是基本的条件语句;

第二层是掌握跨库表提取数据的能力,不同的join有不同的用法;

第三层是优化SQL语句,通过优化嵌套、筛选的逻辑层次和遍历次数等,减少个人时间浪费和系统资源消耗。

其次是理解业务需求的能力,比如业务需要“销售额”这个字段,相关字段至少有产品销售额和产品订单金额,其中的差别在于是否含优惠券、运费等折扣和费用。包含该因素即是订单金额,否则就是产品单价×数量的产品销售额。

四.数据挖掘

数据挖掘是面对海量数据时进行数据价值提炼的关键,以下是算法选择的基本原则:

► 没有最好的算法,只有最适合的算法,算法选择的原则是兼具准确性、可操作性、可理解性、可应用性。

► 没有一种算法能解决所有问题,但精通一门算法可以解决很多问题。

► 挖掘算法最难的是算法调优,同一种算法在不同场景下的参数设定相同,实践是获得调优经验的重要途径。

在数据挖掘阶段,数据分析师要掌握数据挖掘相关能力

一是数据挖掘、统计学、数学基本原理和常识;

二是熟练使用一门数据挖掘工具,Clementine、SAS或R都是可选项,如果是程序出身也可以选择编程实现;三是需要了解常用的数据挖掘算法以及每种算法的应用场景和优劣差异点。

五.数据分析

数据分析相对于数据挖掘更多的是偏向业务应用和解读,当数据挖掘算法得出结论后,如何解释算法在结果、可信度、显著程度等方面对于业务的实际意义,如何将挖掘结果反馈到业务操作过程中便于业务理解和实施是关键。

六.数据展现

数据展现即数据可视化的部分,数据分析师如何把数据观点展示给业务的过程。数据展现除遵循各公司统一规范原则外,具体形式还要根据实际需求和场景而定。基本素质要求如下:

► 工具:PPT、Excel、Word甚至邮件都是不错的展现工具,任意一个工具用好都很强大。

► 形式:图文并茂的基本原则更易于理解,生动、有趣、互动、讲故事都是加分项。

► 原则:领导层喜欢读图、看趋势、要结论,执行层欢看数、读文字、看过程。

► 场景:大型会议PPT最合适,汇报说明Word最实用,数据较多时Excel更方便。

最重要一点,数据展现永远辅助于数据内容,有价值的数据报告才是关键。

七.数据应用

数据应用是数据具有落地价值的直接体现,这个过程需要数据分析师具备数据沟通能力、业务推动能力和项目工作能力。

► 数据沟通能力。深入浅出的数据报告、言简意赅的数据结论更利于业务理解和接受,打比方、举例子都是非常实用的技巧。

► 业务推动能力。在业务理解数据的基础上,推动业务落地实现数据建议。从业务最重要、最紧急、最能产生效果的环节开始是个好方法,同时要考虑到业务落地的客观环境,即好的数据结论需要具备客观落地条件。

► 项目工作能力。数据项目工作是循序渐进的过程,无论是一个数据分析项目还是数据产品项目,都需要数据分析师具备计划、领导、组织、控制的项目工作能力。

image 各位宝宝们,如果对【19应届生】有任何建议的,可以在菜单“联系我们”加我们工作人员的客服号反馈哦,一起加油吧~! image

相关文章

网友评论

      本文标题:程序员面试修炼13 | BAT面试必考算法题

      本文链接:https://www.haomeiwen.com/subject/jyjkjftx.html