Fork me on GitHub

求数组中第k大的数

求一个数组中第k大的数,我第一印象是冒泡,因为只要冒泡k趟即可,第一趟冒泡第一大,第二次冒泡第二大,第k次冒泡第k大,时间复杂度为O(kn),n为数组长度。但是我们都知道快速排序是对冒泡的改进,降低冒泡的递归深度,使时间复杂度降低到O(nlgn),为什么不用快排呢?那么快排的时间复杂度又是多少呢?

因为快排每次将数组划分为两组加一个枢纽元素,每一趟划分你只需要将k与枢纽元素的下标进行比较,如果比枢纽元素下标大就从右边的子数组中找,如果比枢纽元素下标小从左边的子数组中找,如果一样则就是枢纽元素,找到,如果需要从左边或者右边的子数组中再查找的话,只需要递归一边查找即可,无需像快排一样两边都需要递归,所以复杂度必然降低。

最差情况如下:假设快排每次都平均划分,但是都不在枢纽元素上找到第k大

推荐系统的评价方案

对于推荐系统的评价有很多的指标,但对于不同的应用采用相同的评价指标可能也会有截然不同的结果,对于同一个应用的不同评价指标对于评价推荐系统的贡献是不一样的。例如采用MAE和RMSE等针对评分预测的评价指标作用于TopN推荐的场景中,可能指标能反映的内容比较有限。

因此,在确定推荐系统应该以什么指标去做效果评价的时候,要先明确你的推荐系统做的是什么事情,使用者对推荐的哪方面内容最感兴趣。

  • 像音乐、电影等推荐场景,应以推荐冷门但符合用户喜好的物品的能力为评价标准之一,为用户挖掘同一套系列的不同物品对用户的贡献不如为用户推荐题材相同但比较冷门的物品,因为后者对用户来说比较难发现,这就体现了推荐系统在音乐、电影等推荐场景的价值;
  • 而对于ResysChina上的技术文章的推荐场景,我更希望系统推荐出来的是符合我最近浏览的文章的主题的,也就是同类的文章,以便于我对某个内容了解更多信息;
  • 而电商平台的推荐则需要根据不同的商品去评价推荐的效果,假如我最近买了一台冰箱,系统一个劲地给我推荐同类产品(冰箱)还有意义吗?而如果我近期买了某种零食,系统给我推荐同类的零食,你可以说它没有意义吗?

GraphX中基于Pregel的单源最短路径详解

GraphX利用Spark这样一个并行处理框架实现了类似Pregel的图计算模型,该计算模型由以下三个主要部分:

  • 节点消息处理的函数
    vprog:(VertexId, VD, A) => VD
    (节点Id, 节点属性, 消息) => 节点属性
  • 节点发送消息的函数
    sendMsg:EdgeTriplet[VD, ED] => Iterator[(VertexId, A)]
    (边元组) => Iterator[(目标节点Id, 消息)]

  • 消息合并函数(功能类似于Hadoop中的combiner)
    mergeMsg:(A, A) => A
    (消息, 消息) => 消息

Pregel算法已经被集中抽象到GraphOps这个类中,下面就通过详解单源最短路径的例子来看看如何使用。

Spark API版本: 1.1.0

几种JavaScript生成GUID的算法

有的时候,我们需要生成一些Token作为标识:如认证后的标识符,资源的提取码等。一个比较常见的算法是生成一个GUID来作为Token,由于GUID的随机性和唯一性特点,作为Token是一个非常可靠的选择。

全局唯一标识符(GUID,Globally Unique Identifier)也称作 UUID(Universally Unique IDentifier) 。GUID是一种由算法生成的二进制长度为128位的数字标识符。GUID主要用于在拥有多个节点、多台计算机的网络或系统中。在理想情况下,任何计算机和计算机集群都不会生成两个相同的GUID。GUID 的总数达到了2^128(3.4×10^38)个,所以随机生成两个相同GUID的可能性非常小,但并不为0。

以下总结几种生成GUID的算法:

  • 算法1:
1
2
3
4
5
6
7
8
9
10
11
12
function generateUUID() {
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = "-";
var uuid = s.join("");
return uuid;
}

Kafka+SparkStreaming--实时流处理实践

kafka 最初由 Linkedin 公司开发,使用 Scala 语言编写,是一个分布式、分区、多副本、多订阅者的日志系统。 Spark Streaming 是大规模流式数据处理的新贵,将流式计算分解成一系列短小的批处理作业。由于 SparkStreaming 对网络流方式的支持, SparkStreaming+Kafka 的日志流式处理方式已越来越普遍。本文将讲解如何利用两者搭建出一套实时流处理系统,并详细列出实际搭建过程中遇到的问题及解决方式。

准备工作

启动集群

  • 启动 zookeeper

进入 zookeeper HOME 目录,执行 $ bin/zkServer.sh start 启动 zookeeper。

  • 启动 kafka server

修正余弦相似度与皮尔森相关系数

在数据分析和数据挖掘过程中,通常需要比较个体之间的相似度,比较常用的三种度量方法分别是:余弦相似度、皮尔森相关系数和修正的余弦相似度。

  • 余弦相似度(Cosine Similarity)

相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。用户一项目评分矩阵可以看作是n维空间上的向量,余弦相似性度量方法是通过计算向量间的余弦夹角来度量用户间相似性的。设向量x和y分别表示用户X和用户Y在n维空间上的评分,则用基于协同过滤推荐算法研究X和Y之间的相似性公式为:

  • 修正的余弦相似度(Adjusted Cosine Similarity、调整余弦相似度)

余弦相似度未考虑到用户评分尺度问题,如在评分区间[1-5]的情况下,对用户X来说评分3以上就是自己喜欢的,而对于用户Y,评分4以上才是自己喜欢的。通过减去用户对项的平均评分,修正的余弦相似性度量方法改善了以上问题。计算公式为: