如何生成数组的n ^ r变体(即重复nCk的变化)

时间:2014-07-29 08:03:39

标签: algorithm c#-4.0 permutation

我的问题是基于topcoder最近的SRM(628 500点问题),我试图通过强力解决字符串解析问题,因为解决方案的数量不能超过5 ^ 5而且我&# 39;非常接近。我的问题是我怎样才能生成n!排列,但在c#中排列n ^ r排列。使用Knuth的词典排列算法的改编,我的解决方案可以工作,但不适用于答案(获胜排列)具有重复字符的情况。

输入示例:" X {}] X {X {}] X]"

        public string ifPossible(string expression)
    {
        char[] c = new char[6] { '(', ')', '{', '}', '[', ']' };
        StringBuilder sb = new StringBuilder(expression);
        int j = 0;
        special(sb);

        while (my_next_permutation(c) && sb.ToString().Contains('X'))
        {
            for(int i = 0; i < sb.Length;i++)
            {
                if (sb[i] == 'X')
                    sb[i] = c[j++];
            }
            special(sb);
            if (sb.Length > 0)
            {
                sb.Clear();
                sb.Append(expression);
                special(sb);
                j = 0;
            }
            else
            {
                break;
            }

        }


        if (sb.Length > 0)
            return "impossible";
        return "possible";
    }
    void special(StringBuilder sb)
    {
        while (sb.ToString().Contains("()") || sb.ToString().Contains("[]") || sb.ToString().Contains("{}"))
        {
            while (sb.ToString().Contains("()"))
                sb.Replace("()", "");
            while (sb.ToString().Contains("[]"))
                sb.Replace("[]", "");
            while (sb.ToString().Contains("{}"))
                sb.Replace("{}", "");
        }
    }
    public Boolean my_next_permutation(char[] a) 
    {
        int N = a.Length, i = N - 2;
        for (; i >= 0; i--)
            if (a[i] < a[i + 1])
                break;
        if (i < 0) return false;

        for (int j = N - 1; j >= i; j--)
        {
            if (a[j] > a[i])
            {
                var temp = a[i];
                a[i] = a[j];
                a[j] = temp;
                break;
            }
        }
        for (int j = i + 1; j < (N + i + 1) / 2; j++)            
        {
            var temp = a[j];
            a[j] = a[N + i - j];
            a[N + i - j] = temp;
        }
        return true;
    }

1 个答案:

答案 0 :(得分:0)

我本可以使用gmch和jrh建议的阵列想法,但我 最终使用了这个:

IEnumerable<string> GetPermutations(char[] list, int? resultSize = null, bool withRepetition = false)
    {
        List<string> l = new List<string>();
        char[] result = new char[resultSize.HasValue ? resultSize.Value : list.Length];
        var indices = new int[result.Length];
        for (int i = 0; i < indices.Length; i++)
            indices[i] = withRepetition ? -1 : indices.Length - i - 2;

        int curIndex = 0;
        while (curIndex != -1)
        {
            indices[curIndex]++;
            if (indices[curIndex] == list.Length)
            {
                indices[curIndex] = withRepetition ? -1 : curIndex - 1;
                curIndex--;
            }
            else
            {
                result[curIndex] = list[indices[curIndex]];
                if (curIndex < indices.Length - 1)
                    curIndex++;
                else
                    yield return new string(result);
            }
        }
   }

我从这个页面得到了这个想法http://noldorin.com/programming/CombinatoricsUtilities.cs.txt 归功于Alex Regueiro。