全排列

 #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);
        }
posted on 2010-07-27 14:34  PeterZhang  阅读(1701)  评论(2编辑  收藏  举报