最长的连续子序列算法

时间:2009-03-17 20:07:14

标签: c# algorithm

我有一个“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中实现。该函数应该返回一个包含最长子序列元素的数组,或者返回原始数组中最长子序列的起始和结束索引。

感谢大家对此进行了尝试。

3 个答案:

答案 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;
}