填写分隔序列

时间:2014-03-27 18:06:56

标签: c# algorithm

我有一个文件,其中包含一个分隔序列号列表作为记录键。我需要填写缺失的序列。所以,如果我有

8
8.2
8.3.4.1

我需要添加

8.1
8.3
8.3.1
8.3.2
8.3.3
8.3.4

我提出了一些算法,但它们都非常复杂并且有太多的情况。有没有一种简单的方法可以做到这一点,还是我必须通过?我正在使用c#,但Java会这样做。

2 个答案:

答案 0 :(得分:0)

一种简单的方法(虽然在某些情况下不是最佳的)将维护一组现有密钥。对于初始序列中的每个键,您可以将所有前面的键添加到该组中。这可以在两个循环中完成:在内部循环中,您将一个键添加到一个集合,并将该键的最后一个数字减少一个,而该数字大于零,在外部循环中,您将一个键的长度减少一个。

然后你只需要按排序顺序输出该组。

答案 1 :(得分:0)

不确定我的解决方案是否易于理解,但我们试试吧。我们的想法是,我们递归地在现有序列之间插入缺失的序列。

首先,您需要解析文件以创建表示现有序列的项目列表。每个项目都应该引用下一个项目(链表的想法)。

public class Item
{
    public int Value { get; set; }
    public Item SubItem { get; set; }
    public Item NextItem { get; set; }

    public Item(int value, Item subItem)
    {
        Value = value;
        SubItem = subItem;
    }

    public Item CreatePreviousItem()
    {
        if (SubItem == null)
        {
            return Value == 1 ? null : new Item(Value - 1, null);
        }

        return new Item(Value, SubItem.CreatePreviousItem());
    }

    public bool IsItemMissingPrior(Item item)
    {
        if (item == null)
        {
            return false;
        }

        return 
            item.Value - Value > 1 
            || (SubItem == null && item.SubItem != null && item.SubItem.Value > 1) //edge case
            || (SubItem != null && SubItem.IsItemMissingPrior(item.SubItem));
    }

    public override string ToString()
    {
        return Value + (SubItem != null ? "." + SubItem : "");
    }
}

假设序列由新行符号分隔,您可以使用以下Parse方法。

private List<Item> Parse(string s)
{
    var result = new List<Item>();
    var numberLines = s.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);

    foreach (var numberLine in numberLines)
    {
        var numbers = numberLine.Split(new[] {'.'}).Reverse();

        Item itemInstance = null;
        foreach (var number in numbers)
        {
            itemInstance = new Item(Convert.ToInt32(number), itemInstance);
        }

        if (result.Count > 0)
        {
            result.Last().NextItem = itemInstance;
        }

        result.Add(itemInstance);
    }

    return result;
}

这是一个递归方法,它在两个现有的

之间插入缺失的序列
private void UpdateSequence(Item item)
{
    if (item.IsItemMissingPrior(item.NextItem))
    {
        var inBetweenItem = item.NextItem.CreatePreviousItem();
        inBetweenItem.NextItem = item.NextItem;
        item.NextItem = inBetweenItem;
        UpdateSequence(item);
    }
}

最后用例:

var inputItems = Parse(inputString);

foreach (var item in inputItems)
{
    UpdateSequence(item);
}

就是这样。要查看结果,您只需要从列表中获取第一个项目,然后继续使用NextItem属性。例如

var displayItem = inputItems.FirstOrDefault();
while (displayItem != null)
{
    Console.WriteLine(displayItem.ToString());
    displayItem = displayItem.NextItem;
}

希望它有所帮助。