字符串的排列 的迭代解法

来源:互联网 发布:中国金融大数据 编辑:程序博客网 时间:2024/06/04 17:41

微软等数据结构+算法面试100题 中第53题

 

53.字符串的排列。
题目:输入一个字符串,打印出该字符串中字符的所有排列。
例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串
abc、acb、bac、bca、cab和cba。

分析:这是一道很好的考查对递归理解的编程题,
因此在过去一年中频繁出现在各大公司的面试、笔试题中。

 

分析:这是一道很好的考查对递归理解的编程题,
因此在过去一年中频繁出现在各大公司的面试、笔试题中。
我们以三个字符abc 为例来分析一下求字符串排列的过程。首先我们固定第一个字符a,求
33
后面两个字符bc 的排列。当两个字符bc 的排列求好之后,我们把第一个字符a 和后面的b
交换,得到bac,接着我们固定第一个字符b,求后面两个字符ac 的排列。现在是把c 放到
第一位置的时候了。记住前面我们已经把原先的第一个字符a 和后面的b 做了交换,为了保
证这次c 仍然是和原先处在第一位置的a 交换,我们在拿c 和第一个字符交换之前,先要把
b 和a 交换回来。在交换b 和a 之后,再拿c 和处在第一位置的a 进行交换,得到cba。我
们再次固定第一个字符c,求后面两个字符b、a 的排列。
既然我们已经知道怎么求三个字符的排列,那么固定第一个字符之后求后面两个字符的排
列,就是典型的递归思路了。

 


void leftrorate(char *p, int n)
{
 char t = *p;
 for(int i=1;i<n;i++)
  p[i-1] = p[i];
 p[n-1] = t;
}

 

//递归解法

void permuation(char *str, int n, int m)
{
if(m==n-1)
{
  printf("%s/n", str);
  return;
 }

 for(int i=m;i<n;i++)
 {
  permuation(str, n, m+1);
 leftrorate(str+m, n-m);
 }
}

//迭代解法

void permuation(char *str, int n)
{
 int i = 0; //转的圈数
 int k = 0; //栈的深度
 std::stack<int> st;

 while(i<n || k>0)
 {
  if(k<n-1 && i<n-k+1)
  {
   //当k<n-1 && 转的不够一圈
   st.push(i);
   k++;
   i=0;
  }
  else
  {
   if(k==n-1)
   {//长度但到字符串长
    printf("%s/n", str);
    leftrorate(str+k-1, n-k+1);
    if(k>0)
    {
     ++st.top(); 
    }
   } 

   if(st.top()==n-k+1)
   {//转的够一圈
    while(st.top()==n-k+1)
    {
     st.pop();
     k--;
     if(k>0)
     {
      ++st.top(); 
     }
     else
      return;
     leftrorate(str+k-1, n-k+1);
    }
    
    i=0;
   }
  }
 }
 
}

int _tmain(int argc, _TCHAR* argv[])
{
 char str[5] = "abcd";
 permuation(str, 4);
 //char str[4] = "abc";
 //permuation(str, 3);
 return 0;
}

原创粉丝点击