未经测试,但我会尝试以下方法:
var sequence = new[] {1, 6, 3, 5, 2, 8};
var isGoingUp = sequence.First() < sequence.Last();
//if the first sequence is going up, invert the sign on the sequence
//this way we can always compare using "<"
var sequenceToCheck = sequence.Select(x => isGoingUp ? -x : x).ToList();
//initial values
int currentLength = 1; //the length of the subsequence found
int startIndex = 0; //the starting index of the subsequence
//check for each item's longest subsequence
for (int i = 0; i < sequenceToCheck.Count; i++)
{
//go from the end towards the beginning and find the longest sequence for i
for (int j = sequenceToCheck.Count - 1; i > j; i--)
{
if (sequenceToCheck[i] < sequenceToCheck[j])
{
//found i's longest subsequence
if (currentLength < j - i + 1)
{
startIndex = i;
currentLength = j - i + 1;
}
break; //don't check any smaller sequences for i
}
}
if(sequenceToCheck.Count - i < currentLength)
break; //no need to check any more, no sequence past this can be longer
}
var subsequence = sequence.Skip(startIndex).Take(currentLength);
您也应该能够在 LINQ 中实现此解决方案,方法是计算从每个点到匹配数字的距离(从末尾开始)。
然而,在 SQL 中实现这一点会稍微困难一些,尽管你绝对可以做到。这是我的尝试和一个有效的 SQL Fiddle 示例:
WITH firstValue AS (
SELECT TOP 1 value
FROM t
ORDER BY id
), lastValue AS (
SELECT TOP 1 value
FROM t
ORDER BY id DESC
), seqToCheck AS (
SELECT id,
CASE WHEN lastValue.value > firstValue.value THEN 0-t.value
ELSE t.value
END AS value
FROM t
CROSS JOIN firstValue
CROSS JOIN lastValue
), subSequences AS (
SELECT s1.id, COALESCE(MAX(s2.id - s1.id + 1),1) AS distance
FROM seqToCheck AS s1
LEFT JOIN seqToCheck AS s2 ON s1.value < s2.value AND s2.id > s1.id
GROUP BY s1.id
), longestSubSequence AS (
SELECT TOP 1 id, distance
FROM subSequences
ORDER BY distance DESC
)
SELECT t.value
FROM t
INNER JOIN longestSubSequence AS l ON t.id >= l.id AND t.id < l.id + l.distance
ORDER BY t.id
id
这假设您有一个不包含 gaps的升序标识列。ROW_NUMBER() OVER(ORDER BY xxxxx)
如果您没有这样的事情,您也可以这样做。
为了使用索引,您可能会使其变得更复杂一些。