创建所有可能的数组而不嵌套for循环
我想生成所有可能的长度为n
数字,并且我的数字的每个数字都有一个来自集合{1,2,...,n-1}
作为数组。 换句话说,我想列出长度为n
且不包括0
所有基数n
。
现在,我能想到的唯一方法是嵌套n for
循环,并使用第(i + 1)个循环分配myArray[i]
,即
int n; int[] myArray = new int[n]; for (int i1 = 1; i1 < n; i1++) myArray[0]=i1; for (int i2 = 1; i2 < n; i2++) myArray[1]=i2; // and so on.... for (int in = 1; in < n; in++) { myArray[n]=in; foreach (var item in myArray) Console.Write(item.ToString()); Console.Write(Environment.NewLine); }
然后在最里面的循环打印每个数组。 显而易见的问题是,对于每个n,我需要手动编写n
for
循环。
从我所读到的,递归似乎是替换嵌套for
循环的最佳方法,但我似乎无法弄清楚如何为递归制作一般方法。
编辑
例如,如果n=3
,我想写出1 1 1
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
。
我们不限于n<11
。 例如,如果n=11
,我们将输出
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 3 ... 1 1 1 1 1 1 1 1 1 1 10 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 2 2 1 1 1 1 1 1 1 1 1 2 3 ... 1 1 1 1 1 1 1 1 1 9 10 1 1 1 1 1 1 1 1 1 10 1 1 1 1 1 1 1 1 1 1 10 2 1 1 1 1 1 1 1 1 1 10 3 ... 10 10 10 10 10 10 10 10 10 9 10 10 10 10 10 10 10 10 10 10 10 1 10 10 10 10 10 10 10 10 10 10 2 ... 10 10 10 10 10 10 10 10 10 10 10
因此,数字的数字可以是1
到10
之间的任何值。 数组myArray
只是用于获取其中一个数字,然后我们打印它,然后继续下一个数字并重复。
一如既往,在考虑递归解决方案时,尝试使用不可变结构来解决问题; 一切都更容易理解。
首先,让我们自己构建一个快速的小不可变堆栈,它将帮助我们跟踪我们当前生成的数量(同时不必担心在递归调用中生成的其他数字…记住,不可变数据可以’改变!):
public class ImmutableStack: IEnumerable { public static readonly ImmutableStack Empty = new ImmutableStack (); private readonly T first; private readonly ImmutableStack rest; public int Count { get; } private ImmutableStack() { Count = 0; } private ImmutableStack(T first, ImmutableStack rest) { Debug.Assert(rest != null); this.first = first; this.rest = rest; Count = rest.Count + 1; } public IEnumerator GetEnumerator() { var current = this; while (current != Empty) { yield return current.first; current = current.rest; } } public T Peek() { if (this == Empty) throw new InvalidOperationException("Can not peek an empty stack."); return first; } public ImmutableStack Pop() { if (this == Empty) throw new InvalidOperationException("Can not pop an empty stack."); return rest; } public ImmutableStack Push(T item) => new ImmutableStack (item, this); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); }
这很简单。 请注意堆栈如何重用数据。 在我们的小程序中会有多少空的不可变结构? 只有一个。 并且包含序列1->2->4
堆栈? 是的,只有一个。
现在,我们实现一个递归函数,只是不断向堆栈添加数字,直到我们达到“纾困”状态。 哪个是? 当堆栈包含n
元素时。 十分简单:
private static IEnumerable generateNumbers(ImmutableStack digits, IEnumerable set, int length) { if (digits.Count == length) { yield return int.Parse(string.Concat(digits)); } else { foreach (var digit in set) { var newDigits = digits.Push(digit); foreach (var newNumber in generateNumbers(newDigits, set, length)) { yield return newNumber; } } } }
好的,现在我们只需要将它与我们的公共方法联系在一起:
public static IEnumerable GenerateNumbers(int length) { if (length < 1) throw new ArgumentOutOfRangeException(nameof(length)); return generateNumbers(ImmutableStack.Empty, Enumerable.Range(1, length - 1).Select(d => d.ToString(CultureInfo.InvariantCulture)), length); }
果然,如果我们称之为:
var ns = GenerateNumbers(3); Console.WriteLine(string.Join(Environment.NewLine, ns.Select((n, index) => $"[{index + 1}]t: {n}")));
我们得到了预期的输出:
[1] : 111 [2] : 211 [3] : 121 [4] : 221 [5] : 112 [6] : 212 [7] : 122 [8] : 222
请注意,生成的指定长度n
的总数是(n - 1) ^ n
,这意味着对于相对较小的length
值,您将获得相当多的数字生成; n = 10
生成3 486 784 401 …
上述就是C#学习教程:创建所有可能的数组而不嵌套for循环分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/957066.html