我有一个“Range”对象数组,其属性为“Offset”和“Length”,如下所示。假设它将按“偏移”升序排序。
范围数组包含:
Offset Length Index
------- ------- -------
100 10 0
110 2 1
112 5 2
117 3 3
300 5 4
305 5 5
400 5 6
405 10 7
415 2 8
417 4 9
421 7 10
428 1 11
429 6 12
500 4 13
504 9 14
在这种情况下,连续的子序列将是:
Sequence #1 indices: 0, 1, 2, 3
Sequence #2 indices: 4, 5
Sequence #3 indices: 6, 7, 8, 9, 10, 11, 12 <-- (longest!!)
Sequence #4 indices: 13, 14
假设只有一个最长的序列。迭代这些项目,我想为每个连续的序列创建一个新的数组并返回最大的数组,但这似乎是次优的。有一个更好的方法吗?我正在C#2.0中实现。该函数应该返回一个包含最长子序列元素的数组,或者返回原始数组中最长子序列的起始和结束索引。
感谢大家对此进行了尝试。
答案 0 :(得分:3)
该问题与连续的子序列问题等无关,但是可以在O(n)时间内解决的简单问题。在我看来,由数组表示的“字符串”不重叠,因此有一个非常简单的算法:将左手食指放在第一行,然后只要你在一个连续的范围内就向下运行右手食指序列。序列结束时,存储长度和起始位置。然后重复一遍。每当您找到比上一条记录更长的序列时,您都会更新起始位置。
答案 1 :(得分:1)
一个简单的线性算法(Python,我确信代码可以改进):
# Your array
arr = [
(100, 10), (110, 2), (112, 5), (117, 3), (300, 5), (305, 5), (400, 5),
(405, 10), (415, 2), (417, 4), (421, 7), (428, 1), (429, 6), (500, 4),
(504, 9)
]
# Where does each element end?
ends = map(sum, arr)
s, e = 0, 0 # start and end of longest contiguous subseq
cur = 0 # length of current contiguous subseq
for j, i in enumerate(range(1, len(arr))):
# See if current element is contiguous with the previous one
if (arr[i][0] == ends[j]):
cur += 1
elif cur > 0:
# If not, we may have found the end of a (currently) longest subseq
if cur > (e - s):
e = j
s = e - cur
cur = 0 # reset subseq length
# The longest contiguous subseq may be at the end of the array
if cur > (e - s):
e = j + 1
s = e - cur
# print the start and end index of the longest contiguous subseq
print(s, e)
答案 2 :(得分:0)
{java中的线性时间解决方案,无需动态编程。最接近的问题是:
增长最快的子序列需要O(N^2)
DP解决方案。
int LongestContiguousIncreasingSubsequence(int[] a)
{
int maxL = 1,currentL=1;
int n=a.length;
for ( int i = 0; i < n-1; i++ )
{
if(a[i+1]>a[i])
currentL++;
else
{
if (currentL>maxL)
maxL=currentL;
currentL=1;
}
}
return maxL;
}