生成排列的唯一列表,不包括元素的顺序

时间:2018-07-13 11:50:00

标签: c#

因此,我发现的所有搜索似乎都给出了具有唯一排列的结果,包括相同的值集,但顺序不同。

所以可以说我有一个数组:

int[] test = {1, 2, 3, 4};

预期结果集为:

1
1,2
1,2,3
1,2,3,4
1,2,4
1,3
1,3,4
1,4
2
2,3
2,3,4
2,4
3
3,4
4

但是,我得到的结果是:

1
1,2
1,2,3
1,2,3,4
2
2,3
2,3,4
3
3,4
4

如您所见,我错过了以下结果:

1,2,4
1,3
1,3,4
1,4
2,4

我使用的代码是:

int[] test = {1, 2, 3, 4};
List<string> results = new List<string>();

for (int i = 0; i < test.Length;)
{
    results = prepareResults(test, results, "", test.Length);

    if (test.Length > 1)
    {
        int[] temp = new int[test.Length - 1];

        for (int j = 1; j < test.Length; j++)
        {
            temp[j - 1] = test[j];
        }

        test = temp;
    }
    else
    {
        break;
    }
}

public List<string> prepareResults(int[] dataSet, List<string> resultsList, string initialResult, int originalLength)
{
    while (dataSet.Length > 1)
    {
        if (initialResult.Length > 0)
        {
           initialResult += ",";
        }
        initialResult += dataSet[0].ToString();

        resultsList.Add(initialResult);

        int[] temp = new int[dataSet.Length - 1];

        for (int j = 1; j < dataSet.Length; j++)
        {
           temp[j - 1] = dataSet[j];
        }

        dataSet = temp;
        resultsList = prepareResults(dataSet, resultsList, initialResult, originalLength);
        return resultsList;
    }

    if (initialResult.Length != (originalLength * 2) - 1)
    {
        if (initialResult.Length > 0)
        {
            initialResult += ",";
        }

        initialResult += dataSet[0].ToString();
        resultsList.Add(initialResult);
    }

    return resultsList;
}

我确定我只是想念一些愚蠢而明显的东西,但是我一直盯着这个看,现在已经尝试了好几个小时了,有什么建议吗?

2 个答案:

答案 0 :(得分:2)

我建议 masking :我们枚举2**n的掩码,从00001111并将这些掩码应用于数组项:

  mask | permutation
  ------------------
  0000 | (empty)
  0001 | 1
  0010 | 2
  0011 | 1, 2
  0100 | 3
  0101 | 1, 3
  ....
  1110 | 2, 3, 4
  1111 | 1, 2, 3, 4  

实施:

   int[] test = { 1, 2, 3, 4 };   

   var result = Enumerable
     .Range(0, 1 << test.Length)
     .Where(mask => mask != 0) // We don't want empty permutation
     .Select(mask => test 
        .Where((v, i) => ((1 << i) & mask) != 0)
        .ToArray());

   Console.Write(string.Join(Environment.NewLine, result
     .Select(item => string.Join(", ", item))));  

结果:

1
2
1, 2
3
1, 3
2, 3
1, 2, 3
4
1, 4
2, 4
1, 2, 4
3, 4
1, 3, 4
2, 3, 4
1, 2, 3, 4

答案 1 :(得分:0)

每次必须使用排列时,我都使用此方法。它使用左移运算符迭代所有可能性。试试看。

    private List<List<int>> GetPermutations(List<int> testValues)
    {
        List<List<int>> result = new List<List<int>>();

        for (int count = 0; count < (1 << testValues.Count); ++count)
        {
            List<int> combinationList= new List<int>();

            for (int i = 0; i < testValues.Count; ++i)
            {
                if ((count & (1 << i)) == 0)
                {
                    combinationList.Add(testValues[i]);
                }
            }
            result.Add(combinationList);
        }

        return result;
    }

我不知道您是否需要完全按照您期望的顺序写。如果需要按此顺序排列,只需将linq应用于结果列表:)