Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检查数组的所有可能排列_C#_Arrays_Algorithm_Loops_Permutation - Fatal编程技术网

C# 检查数组的所有可能排列

C# 检查数组的所有可能排列,c#,arrays,algorithm,loops,permutation,C#,Arrays,Algorithm,Loops,Permutation,我正在创建一个程序,需要检查所有可能的排列。假设我们有1,2,3,程序会很好地工作,并向我展示所有可能的:1,3,2,1,3,1,3,1,2和3,2,1,但是我也希望它能够尝试这样的组合 1,1,1 2,2,2 1,2,2 3,3,2 i、 包括所有可能的组合。。这是我的密码: public static bool NextPermutation<T>(T[] elements) where T : IComparable<T> { // More efficie

我正在创建一个程序,需要检查所有可能的排列。假设我们有1,2,3,程序会很好地工作,并向我展示所有可能的:1,3,2,1,3,1,3,1,2和3,2,1,但是我也希望它能够尝试这样的组合

1,1,1

2,2,2

1,2,2

3,3,2

i、 包括所有可能的组合。。这是我的密码:

public static bool NextPermutation<T>(T[] elements) where T : IComparable<T>
{
    // More efficient to have a variable instead of accessing a property
    var count = elements.Length;

    // Indicates whether this is the last lexicographic permutation
    var done = true;

    // Go through the array from last to first
    for (var i = count - 1; i > 0; i--)
    {
        var curr = elements[i];

        // Check if the current element is less than the one before it
        if (curr.CompareTo(elements[i - 1]) < 0)
        {
            continue;
        }

        // An element bigger than the one before it has been found,
        // so this isn't the last lexicographic permutation.
        done = false;

        // Save the previous (bigger) element in a variable for more efficiency.
        var prev = elements[i - 1];

        // Have a variable to hold the index of the element to swap
        // with the previous element (the to-swap element would be
        // the smallest element that comes after the previous element
        // and is bigger than the previous element), initializing it
        // as the current index of the current item (curr).
        var currIndex = i;

        // Go through the array from the element after the current one to last
        for (var j = i + 1; j < count; j++)
        {
            // Save into variable for more efficiency
            var tmp = elements[j];

            // Check if tmp suits the "next swap" conditions:
            // Smallest, but bigger than the "prev" element
            if (tmp.CompareTo(curr) < 0 && tmp.CompareTo(prev) > 0)
            {
                curr = tmp;
                currIndex = j;
            }
        }

        // Swap the "prev" with the new "curr" (the swap-with element)
        elements[currIndex] = prev;
        elements[i - 1] = curr;

        // Reverse the order of the tail, in order to reset it's lexicographic order
        for (var j = count - 1; j > i; j--, i++)
        {
            var tmp = elements[j];
            elements[j] = elements[i];
            elements[i] = tmp;
        }

        // Break since we have got the next permutation
        // The reason to have all the logic inside the loop is
        // to prevent the need of an extra variable indicating "i" when
        // the next needed swap is found (moving "i" outside the loop is a
        // bad practice, and isn't very readable, so I preferred not doing
        // that as well).
        break;
    }

    // Return whether this has been the last lexicographic permutation.
    return done;
}
这是我如何使用它的一个简单示例

        var arr = new[] {0, 1, 2,};
        var conditions = new[] {true, false, true};
        int count = 0;

        while (!NextPermutation(arr))
        {
            List<bool> tempConditions = new List<bool>();
            for (int i = 0; i < arr.Length; i++)
            {
                tempConditions.Add(conditions[arr[i]]);
                Console.Write(tempConditions[i] + " ");
            }
            count++;
            Console.WriteLine();
        }
        Console.WriteLine("count : {0}", count);

1,1,2,2,2等等不是排列,它们是变体。将会有数不清的人

您可以这样生成它们:

// you can do precise powering if needed
double number_of_variations = Math.Pow(count, count); 
T[] result = new T[count];

for (int i = 0; i < number_of_variations; ++i) {
    int x = i;
    for (int j = 0; j < count; ++j) {
        result[j] = elements[x % count];
        x /= count;
    }
    // do something with one of results
}

可以使用返回IEnumerable的方法执行此操作,如下所示:


你好像没问什么问题。。。?您需要什么帮助?如何将方法NextPermutation更改为同样经过1,1,1,1,1,2等。正如我经常问的那样,如果您是人类,您将如何进行?为什么要为这样的任务要求这个?人类将以完全不同的方式达到目的result@KOPEUE您不是在问问题。您可能希望编辑此文件,以便它能够编译。但在那之后它会起作用的完成,并将int替换为泛型T以适合原始问题。
using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    public static class Program
    {
        public static void Main()
        {
            string[] test = {"A", "B", "C", "D"};

            foreach (var perm in PermuteWithRepeats(test))
                Console.WriteLine(string.Join(" ", perm));
        }

        public static IEnumerable<IEnumerable<T>> PermuteWithRepeats<T>(IEnumerable<T> sequence)
        {
            return permuteWithRepeats(sequence, sequence.Count());
        }

        private static IEnumerable<IEnumerable<T>> permuteWithRepeats<T>(IEnumerable<T> sequence, int count)
        {
            if (count == 0)
            {
                yield return Enumerable.Empty<T>();
            }
            else
            {
                foreach (T startingElement in sequence)
                {
                    IEnumerable<T> remainingItems = sequence;

                    foreach (IEnumerable<T> permutationOfRemainder in permuteWithRepeats(remainingItems, count - 1))
                        yield return new[]{startingElement}.Concat(permutationOfRemainder);
                }
            }
        }
    }
}