如何从C#中的整数列表中找到增长最长的整数子序列?
答案 0 :(得分:2)
你只需要深入研究一个较小的问题,即在给定起点的情况下找到增加序列的长度。
在伪代码中,这就像:
def getSeqLen (int array[], int pos):
for i = pos + 1 to array.last_element:
if array[i] <= array[i-1]:
return i - pos
return array.last_element + 1 - pos
然后逐步浏览数组,查看这些单独的序列。您知道序列必须在特定点分开,否则序列会更长。换句话说,这些增加的序列没有重叠:
def getLongestSeqLen (int array[]):
pos = 0
longlen = 0
while pos <= array.last_element:
len = getSeqLen (array, pos)
if len > longlen:
longlen = len
pos = pos + len
return longlen
通过图解说明,请考虑以下顺序:
element#: 0 1 2 3 4 5 6 7 8 9 10 11 12
value: 9 10 12 7 8 9 6 5 6 7 8 7 8
^ ^ ^ ^ ^
在这种情况下,^
个字符标记子序列的明确边界。
从元素0开始,getSeqLen
返回3.由于这大于当前最长的0,我们保存它并将3加到当前位置(得到3)。
然后在元素3处,getSeqLen
返回3.由于这不大于当前最长的3,我们忽略它但我们仍然将3加到当前位置(得到6)。
然后在元素6处,getSeqLen
返回1.由于这不大于当前最长的3,我们忽略它但我们仍然将1加到当前位置(得到7)。
然后在元素7处,getSeqLen
返回4.由于这大于当前最长的3,我们保存它并将4加到当前位置(得到11)。
然后在元素11处,getSeqLen
返回2.由于这不大于当前最长的4,我们忽略它但我们仍然将2加到当前位置(得到13)。
然后,由于元素13超出了结尾,我们只返回找到的最长长度(4)。
答案 1 :(得分:1)
您想要的是patience sorting。它可以计算长度,并找到序列。
答案 2 :(得分:1)
这是我的解决方案:
public static int[] FindLongestSequence(int[] seq)
{
int c_min = 0, c_len = 1;
int min = 1, len = 0;
for (int i = 0; i < seq.Length - 1; i++)
{
if(seq[i] < seq[i+1])
{
c_len++;
if (c_len > len)
{
len = c_len;
min = c_min;
}
} else
{
c_min = i+1;
c_len = 1;
}
}
return seq.Skip(min).Take(len).ToArray();
}
}
答案 3 :(得分:0)
创建三个变量:两个整数列表和一个整数。最初将整数设置为int.MinValue。在迭代列表时,如果当前值大于整数变量,则将其附加到列表1.如果不是这种情况,请清除列表1,但如果列表长于列表2,则首先将列表1复制到列表2。完成序列后,返回较长的列表(及其长度)。
答案 4 :(得分:0)
作为一个性能提示,如果你当前最长的子字符串比字符串的其余部分长,你可以在那里调用它!
答案 5 :(得分:0)
我已在O(n log n)时间内解决了这个问题:
http://www.olhovsky.com/2009/11/extract-longest-increasing-sequence-from-any-sequence/
最终序列中的项目,用于形成链接列表。
class SeqItem():
val = 0 # This item's value.
prev = None # The value before this one.
def __init__(self, val, prev):
self.val = val
self.prev = prev
从序列序列中提取最长的非递减子序列。
def extract_sorted(seq):
subseqs = [SeqItem(seq[0], None)] # Track decreasing subsequences in seq.
result_list = [subseqs[0]]
for i in range(1, len(seq)):
result = search_insert(subseqs, seq[i], 0, len(subseqs))
# Build Python list from custom linked list:
final_list = []
result = subseqs[-1] # Longest nondecreasing subsequence is found by
# traversing the linked list backwards starting from
# the final smallest value in the last nonincreasing
# subsequence found.
while(result != None and result.val != None):
final_list.append(result.val)
result = result.prev # Walk backwards through longest sequence.
final_list.reverse()
return final_list
Seq跟踪构造的每个非增加子序列的最小值。 在seq中查找大于search_val的最小项。 如果这样的值不存在,请将search_val附加到seq,创建 一个新的非增加子序列的开始。 如果确实存在这样的值,则替换该位置的seq中的值,并且 如果,search_val将被视为最长子句的新候选者 添加以下非增加子序列中的值。 Seq保证按升序排列。 返回应添加到结果中的seq元素的索引。
def search_insert(seq, search_val, start, end):
median = (start + end)/2
if end - start < 2: # End of the search.
if seq[start].val > search_val:
if start > 0:
new_item = SeqItem(search_val, seq[start - 1])
else:
new_item = SeqItem(search_val, None)
seq[start] = new_item
return new_item
else: # seq[start].val <= search_val
if start + 1 < len(seq):
new_item = SeqItem(search_val, seq[start])
seq[start + 1] = new_item
return new_item
else:
new_item = SeqItem(search_val, seq[start])
seq.append(new_item)
return new_item
if search_val < seq[median].val: # Search left side
return search_insert(seq, search_val, start, median)
else: #search_val >= seq[median].val: # Search right side
return search_insert(seq, search_val, median, end)
使用如下代码:
import random
if __name__ == '__main__':
seq = []
for i in range(100000):
seq.append(int(random.random() * 1000))
print extract_sorted(seq)
答案 6 :(得分:0)
一种方法是在Aggregate方法的帮助下:
var bestSubSequence = listOfInts.Skip(1).Aggregate(
Tuple.Create(int.MinValue, new List<int>(), new List<int>()),
(curr, next) =>
{
var bestList = curr.Item2.Count > curr.Item3.Count ? curr.Item2 : curr.Item3;
if (curr.Item1 > next)
return Tuple.Create(next, new List<int> {next}, bestList);
curr.Item2.Add(next);
return Tuple.Create(next, curr.Item2, bestList);
}).Item3;
当我开始编写它时,它没有像我希望的那样好,我认为其他更直接的方法更好,更容易遵循,但它可能会对这些任务的方式提供不同的视角可以解决。