我有一个文件,其中包含一个分隔序列号列表作为记录键。我需要填写缺失的序列。所以,如果我有
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会这样做。
答案 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;
}
希望它有所帮助。