【发布时间】:2015-03-21 18:50:51
【问题描述】:
问题
tl;dr - 下面的代码显示了我希望通过尝试某种不同的方法来改进的算法。
现在是冗长的解释。
给定一个整数列表,我想找到与序列的原始起点相同或更高的每个连续整数序列。该序列也应该比排名更高的连续序列更长。
你可能很困惑。让我来说明一下我的意思。
当我有一个整数列表时,我可以将其展开以表示其范围。示例:
2,1,1,3,3,1
变成
-,-,-,3,3,-
2,-,-,2,2,-
1,1,1,1,1,1
如您所见,每个整数值都在其各自的行中,递减的值填充在其下方的列中。请注意,上述过程不必在算法中执行。
我现在想返回一个级别/行上未被另一个序列完全覆盖的每个序列。
例如,这里的列表中没有 0,这意味着 1 的基线具有最大长度。返回值之一现在将是 [1, 6, 5]:1 表示序列组成的数字,6 表示序列的长度,5 表示序列的最终索引。
对于中间一排,我们只有两个。我们来分析一下。这里的第一个序列是开头的单两个。它的返回值为 [2,1,0]。然后是两个空白,然后是另外两个二。可是等等!不要添加它们!二的顺序完全被上面的三覆盖。所以实际上,我们已经完成了这一行。
在最上面一行,我们可以添加三个序列:[3,2,4]
现在的最终输出是
[[1,6,5],[2,1,0],[3,2,4]]
再举几个例子
为了清楚起见,这里有几个例子。它们是 100% 完整和正确的,我已经检查了很多次。
[3,3,3,2,1] -> [[1,5,4],[2,4,3],[3,3,2]]
[7,7,3,0,1,2,3] -> [[1,3,6],[2,2,6],[3,3,2],[3,1,6],[7,2,1]]
[0,0,0] -> []
[0,1,0,4,0,1,0] -> [[1,1,1],[4,1,3],[1,1,5]]
到目前为止我的方法
我想到了一种相当复杂的方法,即从最高出现次数到 1 迭代列表中的值。每当我遇到一个序列时,我会保存它,然后将它的所有元素减一。不过,在我做后者之前,我检查序列的开始和结束索引的左侧或右侧的值是否分别低于序列中的数字。例如,在以下情况下是正确的:
[2,4,4,4,1], looking at 3*4
[1,8,8], looking at 2*8
[9,9,9,8], looking at 3*9
[9,7,4], looking at 2*7 (sequence doesn't formally exist as [7,7],
but would be in the results, as described above)
如果是这种情况,那么我会递减序列的所有值以适应其周围环境。
让我们用一个简单的列表来完成这个过程:
[4,4,2,1,1,3]
我们首先检查四肢。开头有两个,多方便啊!左边没有值,右边的值是 2 ... 所以 1 小 2 点。所以......我们可以愉快地减少列表中的所有元素。不过,在此之前,我们将序列 ([4,2,1]) 的值传递给一个变量。之后,我们读取最高的周围整数值,将其分配给序列的所有元素并得到:
[2,2,2,1,1,3]
啊哈!现在它与右边的 2 相等。我们现在需要做的就是检查是否有任何值为 3 的整数。嗯,huzzah,有一个小家伙坐在角落里。同样,我们保存序列的值 ([3,1,5]) 并为每个元素分配最高的周围整数,恰好是 1:
[2,2,2,1,1,1]
又一次。我们返回 [2,3,2]。
[1,1,1,1,1,1]
为什么,这看起来不熟悉。我们所要做的就是返回 [1,6,5] 就完成了。
最终输出为[[4,2,1],[3,1,5],[2,3,2],[1,6,5]]。
懒得看更多例子了……反正这篇文章太长了。
代码
是的,我已经有了一些代码。这里是:
def ListProcessing(listL, length, freq):
#to detect end of array and not miss out on last sequences
listL.extend([0])
#Iterating over all unique elements that appear in the list from top to
#bottom, leaving out elements under or equal to _length_
for checkNum in reversed(list(set(sorted(listL))-set(range(length)))):
seqLen = 0
#Iterate over list
for index, val in enumerate(listL):
#current element higher than checkNum?
#Yes -> increase counter of the sequence length
if val >= checkNum:
seqLen += 1
#No -> Reset seqLen. If seqLen is high enough, replace sequence with
# sequence of highest neighbouring elements and yield the seq.
else:
if seqLen > freq-1:
newVal = max(val, listL[index-seqLen-1])
listL[index-seqLen:index] = [newVal] * seqLen
yield(checkNum, seqLen, index-1)
seqLen = 0
AFAIK 它完全符合我的要求。
那么 - 有什么问题?
如上所述,我的算法已经有效。然而,这种方法似乎有点复杂,我相信有更好的方法。我很想听听另一种方法。
目前正在使用 array.array 模块实现这一点,以使其更快。如果有人想尝试用它实现自己的方法,我会非常激动。
欢迎未实现的概念/想法!
【问题讨论】: