K语言求整数数组最长连续序列长度的实现问题咨询
K语言求整数数组最长连续序列长度的实现问题咨询
大家好,我最近在尝试用K语言实现从整数列表里找出最长连续数字序列的功能,目前写的代码在第一个测试案例里工作正常,但到第二个案例时结果不符合预期,想请各位帮忙看看怎么修改才能得到正确结果。
先给大家看正常工作的测试案例:
q) list:100 4 200 1 3 2 q)st where (deltas st:asc list)=1 1 2 3 4 q)count st where (deltas st:asc list)=1 4
这段代码能正确输出连续序列1 2 3 4,长度为4,符合预期。
但下面的测试案例就出问题了:
q)list 10 15 1 2 3 4 5 11 12 q)st where (deltas st:asc list)=1 1 2 3 4 5 11 12 // 我预期的结果应该是1 2 3 4 5 q)count st where (deltas st:asc list)=1 7
当前代码把两段连续序列(1-5和11-12)合并输出了,而我想要的是最长的那一段连续序列,也就是1 2 3 4 5,对应的长度是5。
解决方案思路
要解决这个问题,我们需要先给排序后的数组里的连续数字块分组,再找到长度最长的那个块。可以借助K语言的rle(游程编码)函数实现这个逻辑,具体步骤如下:
- 对原始列表排序
- 计算排序后列表中相邻元素的差值
- 用
rle对差值序列编码,得到连续相同差值的长度和对应值 - 筛选出差值为1的块,找到其中长度最长的那个
- 根据最长块的位置,从排序后的列表中提取对应连续序列
具体实现代码
针对上述问题案例,修改后的代码如下:
q)list:10 15 1 2 3 4 5 11 12 q)st:asc list // 先排序列表 q)(l;v):rle 1_deltas st // 对相邻差值做游程编码,l是块长度,v是对应差值 q)idx:max i where v=1 // 找到差值为1的块中长度最长的那个的索引 q)start:sum l[0:idx] // 计算该块在排序后列表中的起始位置 q)end:start+l[idx] // 计算该块的结束位置 q)st[start:end+1] // 提取对应的最长连续序列 1 2 3 4 5 q)count st[start:end+1] // 计算最长连续序列的长度 5
代码解释
1_deltas st:计算排序后列表的相邻元素差值,去掉第一个无效差值(deltas的第一个结果是第一个元素本身),得到真正的相邻差序列。rle函数会把连续相同的差值分成块,比如这个案例的差值序列是1 1 1 1 6 1 4,编码后得到块长度l:4 1 1 1、对应差值v:1 6 1 4。- 通过
max i where v=1找到差值为1的块中长度最大的那个索引(这里第一个块长度4是最大的,索引为0)。 - 最后计算该块在排序后列表中的起止位置,提取元素就得到了最长连续序列。
如果存在多个长度相同的最长连续序列,这段代码会返回第一个出现的序列。如果需要获取所有最长序列,可以把idx的计算改成idxs:i where v=1 and l=max l where v=1,再逐个提取对应序列即可。
备注:内容来源于stack exchange,提问作者Rajasekhar




