我正在努力制作算法" shuffles"一组数字以这样的方式从0开始按升序排序,下一个数字不得超过前一个+ 1,它们的长度也必须为15,并且必须包含数字集中的每个数字。例如,如果我们有数字:
0,1
所需的输出是:
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1(是的,这是14个零)
0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
...
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1
如果数字是
,也一样0,1,2
0,0,0,0,0,0,0,0,0,0,0,0,0,1,2(必须包括每个数字)
我尝试了以下内容,但我失败了:
版本1
private static List<List<int>> GetNumbers(int lastNumber)
{
if (lastNumber == 0)
{
return new List<List<int>> { new List<int> { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
}
int[] setOfNumbers = new int[lastNumber + 1];
List<List<int>> possibleRoutes = new List<List<int>>().ToList();
for (int i = 0; i <= lastNumber; i++)
{
setOfNumbers[i] = i;
}
var temp = new List<int>();
int[] possibleRoute = new int[15];
for (int j = 0; j < size - lastNumber; j++)
{
possibleRoute[j] = 0;
}
for (int j = lastNumber; j < possibleRoute.Length; j++)
{
for (int k = j; k > 0; k--)
{
possibleRoute[k] = lastNumber - 1;
}
for (int i = size - 1; i >= j; i--)
{
possibleRoute[i] = lastNumber;
}
possibleRoutes.Add(possibleRoute.ToList());
generalCounter++;
}
return possibleRoutes;
}
版本2
private static List<List<int>> GetNumbers(int lastNumber)
{
if (lastNumber == 0)
{
return new List<List<int>> {new List<int> {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
}
int[] setOfNumbers = new int[lastNumber + 1];
List<List<int>> possibleRoutes = new List<List<int>>().ToList();
for (int i = 0; i <= lastNumber; i++)
{
setOfNumbers[i] = i;
}
var temp = new List<int>();
int[] possibleRoute = new int[15];
for (int j = 0; j < size - lastNumber; j++)
{
possibleRoute[j] = 0;
}
for (int i = 1 ; i <= lastNumber ; i++)
{
int newNumber = lastNumber - i;
for (int k1 = i + 1; k1 <= size; k1++)
{
for (int j = possibleRoute.Length - 1; j > k1 - i - 1; j--)
{
possibleRoute[j] = lastNumber;
}
for (int k = i; k <= k1 - 1; k++)
{
possibleRoute[k] = newNumber;
}
possibleRoutes.Add(possibleRoute.ToList());
generalCounter++;
}
}
return possibleRoutes;
}
答案 0 :(得分:1)
我误解了这个问题。开始这个答案。
让我们以另一种方式陈述问题。
我们有很多项目,十五项。
我们有多个数字,比如说0,1,2。
我们想知道x 0,y和z两个组合是什么,x + y + z = 15,x,y和z都是至少一个。
所以,将它减少到一个更容易的问题。假设有一个零。 现在你可以解决更容易的问题了吗?问题现在变小了:现在的问题是生成长度为14且至少有一个1和一个2&#34;的所有序列。你看到如何解决更容易的问题?
如果没有,请将其分解为更容易的问题。假设有一个1.你能解决这个问题吗?现在的问题是找到所有序列中包含13个2的序列,并且只有其中的一个。
现在假设有两个1。你能解决那里的问题吗?
您是否看到如何使用解决方案解决更难的问题?
答案 1 :(得分:0)
与这样的各种问题一起使用的简单策略是按字典顺序列出可能性。在伪代码中,你会做这样的事情:
按字典顺序将V设置为第一个可能的序列。
重复以下步骤:
对于许多情况,您可以通过在V中向后搜索最右侧的“可递增”值来解决第二个子问题(“将V设置为下一个序列”);也就是说,可以递增的最右边的值导致序列的可能前缀。一旦该值递增(按最小量),您将找到以该前缀开头的最小序列。 (这是第一个子问题的简单概括:“找到最小序列”。)
在这种情况下,这两个子问题都很简单。
如果值不是集合中的最大数字,则它是可递增的,并且它与前面的值相同。它只能递增到集合中的下一个更大的值。
要查找以k
结尾的前缀开头的最小序列,首先要查找集合中大于k
的所有值,并在结尾处按顺序排列的序列。然后使用k
填写前缀(如果有)之后的其余值。
要将此方法应用于不同的枚举问题,请参阅https://stackoverflow.com/a/30898130/1566221。它也是next_permutation
标准实现的本质。