全排列

 #region

        /// <summary>

        /// 全排列 递归 考虑重复

        /// Peter

        /// </summary>

        public static String[] Permutation(String s)

        {

            if (s.Length == 1)

            {

                String[] res = new String[1];

                res[0] = s;

                return res;

            }

            else

            {

                StringBuilder sbuilder = new StringBuilder();



                Char[] cs = s.ToCharArray();

                Array.Sort(cs);

                s = new String(cs);

                Char pre = '0';

                for (Int32 i = 0; i < s.Length; i++)

                {

                    if (i == 0)

                    {

                        pre = s[i];

                        sbuilder.Append(String.Join(",", Merge(s[i], Permutation(s.Substring(0, i) + s.Substring(i + 1)))) + ",");

                    }

                    else

                    {

                        if (s[i] == pre)

                        {

                            continue;

                        }

                        else

                        {

                            sbuilder.Append(String.Join(",", Merge(s[i], Permutation(s.Substring(0, i) + s.Substring(i + 1)))) + ",");

                            pre = s[i];

                        }

                    }

                }

                return sbuilder.ToString().Split(new char[]{','},StringSplitOptions.RemoveEmptyEntries);

            }

        }



        public static String[] Merge(Char c, String[] s)

        {

            for (Int32 i = 0; i < s.Length; i++)

            {

                s[i] = c + s[i];

            }

            return s;

        }



        #endregion





        #region

        /// <summary>

        /// 全排列 非递归 没有重复元素!

        /// Peter

        /// 给定已知序列 P =  A1A2A3An ( Ai!=Aj , (1<=i<=n  , 1<=j<=n, i != j  ) )

        /// 方法为:

        /// 1.从低位到高位(从后向前),找出“不符合趋势”的数字。即找到一个Pi,使P(i) < P(i+1)。

        /// 若找不到这样的pi,说明我们已经找到最后一个全排列,可以返回了。

        /// 2.在 P(i+1)P(i+2)Pn 中,找到一个P(j),便得 P(j)"刚刚好大于"P(i). 

        /// ("刚刚好大于"的意思是:在 P(i+1)P(i+2)Pn 中所有大于P(i)的元素构成的集合中最小的元素.)

        /// 3.交换 P(i) , P(j) 的位置.注意:此处不改变i和j的值,改变的是P(i)和P(j).

        /// 4.交换后, P(1)P(2)P(3)P(n)  并不是准确的后一个排列。因为根据第1步的查找,我们有P(i+1) > P(i+2) > . > Pn

        /// 即使进行了Pi和Pj的交换,这仍然是这一部分最大的一个排列。将此排列逆序倒置(变成最小的排列)即为所求的下一个排列.

        /// 5.重复步骤1-4,直到步骤1中找不到“不符合趋势”的数字.

        /// </summary>

        

        public static List<String> Permutation1(String s)

        {

            Char[] cs = s.ToCharArray();

            Array.Sort(cs);

            s = new String(cs);

            List<String> list = new List<String>();

            list.Add(s);



            while (true)

            {

                s = FindNext(s);



                if (s == null)

                    break;



                list.Add(s);

            }

            return list;



        }

        public static String FindNext(String cur)

        {

            Int32 p1, p2;

            for (Int32 i = cur.Length - 1; i > 0; i--)

            {

                if (cur[i - 1] < cur[i])

                {

                    p1 = i - 1;

                    char min = cur[i];

                    p2 = i;

                    for (Int32 j = i; j < cur.Length; j++)

                    {

                        if (cur[j] > cur[p1])

                        {

                            if (cur[j] < min)

                            {

                                min = cur[j];

                                p2 = j;

                            }

                        }

                    }

                    Char[] cs = cur.ToCharArray();

                    char temp = cs[p1];

                    cs[p1] = cs[p2];

                    cs[p2] = temp;

                    Array.Reverse(cs, p1 + 1, cs.Length - p1 - 1);



                    return new String(cs);

                }

            }



            return null;

        }



        #endregion



        static void Main(string[] args)

        {



            Program p = new Program();



            String str = "abcc";



            Int32 start = Environment.TickCount;

            String[] res = Program.Permutation(str);

            Console.WriteLine("time :" + (Environment.TickCount - start));



            Console.WriteLine(res.Length);

            foreach (String s in res)

                Console.WriteLine(s);



            Console.WriteLine("--------------");

            start = Environment.TickCount;

            List<String> res2 = Program.Permutation1(str);

            Console.WriteLine("time :" + (Environment.TickCount - start));



            Console.WriteLine(res2.Count);

            foreach (String s in res2)

                Console.WriteLine(s);

        }

你可能感兴趣的:(全排列)