我有以下情况,我希望得到一个没有大量循环和切片的通用解决方案。
首先:
我初始化N
通过它我计算了列表大小(初始大小):
通过此等式N(N-1)/2
..
假设我设置了N = 5
,因此初始尺寸为10
。
之后我用一些方法用一个和零填充列表。
像这样:
0 1 0 1 1 1 0 1 0 1
此列表根据N进行分段,其中段为(N-1)。
所以
0 1 0 1
1 1 0
1 0
1
[0 1 0 1] [1 1 0] [1 0] [1]
我想要做的是,如果我再次输入任何数字作为输入N:
使用正确的移位保持以前的数据
根据新尺寸。例如,如果N = 6,那么尺寸将为15
所以我将有5个段而不是4个
我想这样:
[0 1 0 1 0 ] [1 1 0 0 ] [1 0 0 ] [1 0 ] [ 0 ]
反之,如果我首先输入N = 7并填充它。然后我输入N = 4
我想做出正确的转变
答案 0 :(得分:2)
LinkedList
似乎是最合适的收藏类。它使您能够从列表中的任何位置以恒定时间插入和删除元素。
下面给出了用于将N增加和减少一个的算法。两个操作都是O(N)。
// the whole list of integers
var data = new LinkedList<int>();
// stores the final node of each segment
var segmentEnds = new LinkedList<LinkedListNode<int>>();
/* INCREASING */
// increase all existing segments by one
var node = segmentEnds.First;
while (node != null)
{
node.Value = data.AddAfter(node.Value, 0);
node = node.Next;
}
// add the last segment of size 1
segmentEnds.AddLast(data.AddLast(0));
/* DECREASING */
if (data.Count > 0)
{
// remove the last element from each segment
node = segmentEnds.First;
while (node != null)
{
var temp = node.Value.Previous;
data.Remove(node.Value);
node.Value = temp;
node = node.Next;
}
// remove the last (now empty) segment
segmentEnds.RemoveLast();
}
答案 1 :(得分:2)
您必须在一个列表中包含这些内容吗?看来你所拥有的是这里的n个列表的列表,因此创建一个大小为N的列表,其中包含大小为1到N的列表。这样,如果你增加N,你只需在每个列表中添加适当数量的0,并创建只有0英寸的新列表。如果你减少N,我不确定规则是什么,但我怀疑相比之下,你只需删除适当数量的短列表,然后删除其他列表中的最后一个元素。
它不具备单个arraylist的作用,但它是存储您描述的数据的更好方法,我会说。无论如何,你总是可以很容易地从我描述的模型中获得平坦的列表......
答案 2 :(得分:2)
也许您应该开始考虑二维并使用List<Segment>
,而Segment
是List<bool>
。通过使用此功能,您应该能够轻松添加/删除段或以您喜欢的方式更改所有段。但这会以某种方式导致重度循环,但我认为如果不在任何级别上循环,你就无法解决这个问题。
答案 3 :(得分:1)
int N = 5;
var array = Enumerable.Range(1, N - 1).Select(i => Fill(i))
.SelectMany(x => x)
.ToArray();
int[] Fill(int len)
{
int[] arr = new int[len];
for (int i = 0; i < len; i++) arr[i] = 1; //Fill
return arr;
}
答案 4 :(得分:1)
基本上,您使用一维列表建模2D数据结构。虽然它有些不正统,但通常会节省内存。
最简单的解决方案是在扩展或收缩列表时制作副本。当您需要缩短或扩展列表时,请创建目标大小的新列表,然后使用两个嵌套循环进行复制,就好像原始列表是2D数据结构一样。制作一个采用row
,column
和N
的映射函数,并将索引返回到与{row, column}
对对应的普通列表中可能会非常有帮助:
private static int MakeIndex(int r, int c, int N) {
return (N*(N+1)-(N-r)*(N+1-r))/2+c;
}
现在,您可以将大小为{r, c}
的列表中的N1
对的索引转换为大小为N2
的列表中同一对的索引。
您可以通过扩展和缩小来改进此解决方案。关键问题是你走的方向:收缩时,前后走;在扩张时,回到前面。