繁体   English   中英

如何在C#中的列表中找到顺序整数?

[英]How do I find sequential integers in a list in C#?

如何从C#中的整数列表中找到增长最长的整数子序列?

你只需要深入研究一个较小的问题,即在给定起点的情况下找到增加序列的长度。

在伪代码中,这类似于:

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)。

你想要所谓的耐心排序 它可以计算长度,并找到序列。

这是我的解决方案:

    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();
    }
}

创建三个变量:两个整数列表和一个整数。 最初将整数设置为int.MinValue。 在迭代列表时,如果当前值大于整数变量,则将其附加到列表1.如果不是这种情况,请清除列表1,但如果列表长于列表2,则首先将列表1复制到列表2。完成序列后,返回较长的列表(及其长度)。

作为一个性能提示,如果你当前最长的子字符串比字符串的其余部分长,你可以在那里调用它!

我在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

从序列seq中提取最长的非递减子序列。

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)

一种方法是在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;

当我开始编写它时,它并没有像我希望的那样好,我认为其他更直接的方法更好,更容易遵循,但它可能会对如何解决这些类型的任务提供不同的视角。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM