数组相似性计算

起因:有一师弟报考一老师,老师发来的测试题目。(应该是测试他的逻辑能力?)

题目:数据有: (1) P.txt文件, 内含从小到大排序的1万个数组; (2) S.txt文件, 内含从小到大排序的1千个数组。两个文件格式均为:(1)每个数组开始为#00001,也就是读到一-行开始为#可以记为读到一个新数组。(2)小数点前有3到4位数字,小数点后有固定的5位数字。(3) 以/n换行。示意如下:

#00001

100.00001

100.10001

……

1999.00005

#00002

100.00002

100.10002

1999.00006

……

#10000

100.00010

……

1999.00040

2、对于S.txt中的每一一个数组,在P.txt中寻找“ 最相似”的数组,返回1千个编号(P.txt中的第几个数组)及“相似度”。每个结果占- -行,以\n结尾,每行第一个数字为编号(一个整数),第二个数字为相似度(一个整数),中间用\t分隔,共1千行,存为R.txt。输入相同的P.txt和S.txt,不同人写的程序输出的R.txt应该是一模一样的。R.txt格式示意如下:

3282288

4899152

5814124

4322124

......

3、"相似”的定义:两个数组里面有几个数字数值相差0.01以内。如S.txt中数组为[100,200,300],P.txt中数组为[200.00001 ,300.00001,1000],这两个数组相似度为2。“最相似”即为数值相差0.01以内的数字最多。注意,S.txt和P.txt数组里的数字只能用于计算一次相似度,不能重复计数,找数值最相近的数字进行计数。如S.txt中数组为[200,300],P.txt中数组为[200.00001 ,200.00002,1000],这两个数组.相似度为1。

要求:语言不限,输出计算结果。

这里简单说下我的思路,有更好的欢迎大家讨论下。

P => database

S => search data

{100.12345 : #P1} 正方向

{100.12346 : #P1}

......

{100.13345 : #P1}

-------------------

{100.11345 : #P1} 负方向

{100.11346 : #P1}

......

{100.12345 : #P1}

这里把 P 中每一个数值的正负 0.01 范围内的数值全部遍历出来存成字典的形式。问题是,小数点后面保留了 5 位数,这样遍历存字典的操作会给计算时的储存带来很大压力。而且在遍历生成正负 0.01 范围内的数的时候也在浪费着计算时间。所以这个方法只是在最后的输出时节省了大量的时间。但整体上并没有正真的做到“快速计算”。

现在对于每个原始数值只保留两位小数如 100.12345 => 100.12,并将小数点后第三位数值信息保留在字典的值中,如:

{100.12 : 3#P1}

这时的key中少了上述步骤中的  100.11 的键值对,也少了 100.13 的键值对,所以将其增加进去并重新定义:

{100.11 : 3#P1} 降格 => {100.11 : jg3#P1}

{100.12 : 3#P1} 零格 => {100.12 : lg3#P1}

{100.13 : 3#P1} 升格 => {100.12 : sg3#P1}

取S中一数组的值 (记为s) 进行相似比较:

if(s == 100.11){

  s 小数点第三位 > 3 (原始数据小数点后第三位)

  print "相似度 + 1"

}

------------------------------------

if(s == 100.12){

  print "相似度 + 1"

}

------------------------------------

if(s == 100.13){

  s小数点第三位 < 3 (原始数据小数点后第三位)

  print "相似度 + 1"

}

------------------------------------

由于上述的字典中很可能是一对多的对应关系,所以将 jg,lg 和 sg 这些信息记录下来,方便比较时确实这个 key 是原始数据的保留小数点后两位的结果还是通过升降 0.01 后得到的结果。

之后的输出并比较选择出最相似的过程,这里省略。欢迎有其他算法进行讨论交流。

猜你喜欢

转载自www.cnblogs.com/zijunlearningclanguage/p/11940247.html