16全排列以及跳台阶问题

一:全排列问题

    题目:输入一个字符串,打印出该字符串中字符的所有排列。

    例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串:abc、acb、bac、bca、cab 和cba。

 

    1:递归算法

    从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,如此递归处理,从而得到所有元素的全排列。

    代码:

void  Permutation(char  * pStr, char  * pBegin)

{

         if(!pStr || !pBegin)

                  return;

 

         char *pCh = NULL;

        

         if(*pBegin == '\0')

         {

             printf("%s\n", pStr);

         }

         else

         {

            for(pCh = pBegin; *pCh != '\0'; ++ pCh)

            {

                          char temp = *pCh;

                          *pCh = *pBegin;

                          *pBegin = temp;

 

                          Permutation(pStr,pBegin + 1);

 

                          temp = *pCh;

                          *pCh = *pBegin;

                          *pBegin = temp;

            }

       }

}

 

    2:非递归算法

    基本思想是:

a:对原始队列进行排序,找到所有排列中最小的一个排列Pmin。

b:找到刚刚好比Pmin大比其它都小的排列P(min+1)。
c:循环执行第二步,直到找到一个最大的排列,算法结束。

    那么如何计算比当前队列更大一点的排列呢?只要对字符串反复求出下一个排列,全排列的也就迎刃而解了。如"1234"的下一个排列就是"1243"。


    举个例子,来考虑"926520"这个字符串,我们从后向前找第一对相邻的递增数字,"20"、"52"、"65"都是递减的,"26"即满足要求,称前一个数字2为替换数,替换数的下标称为替换点

    替换点之后的数都是递减排序的,这样,替换点之后的数已经是最大的数了(6520)。此时,再从最后开始往前,找第一个比替换数大的数。0、2都不行,5可以,将5和2交换得到"956220",此时,替换点上的数已经换成了比2稍大一点的5,替换点之后的数依然是递减排列的。这样,将替换点后的字符串"6220"颠倒即得到"950226"。这就是"926520"下一排列。

    上述的思想,参见”26520”这个数,”6520”已经递减排列,也就是最大的4位数了。目前的最高位是2,所以,要想找一个比”26520”还大的数,就要找到比2还大的最高位,所以从后往前找,找到了5,交换2和5,此时变成了56220,替换点之后的数依然是递减排列的:5之后的数是6220,同样是最大的4位数了,只要反转,变成0226就成了最小的数了。

代码如下:

void  nocur_permutation(char *a,int length) 

         if(length<2) return; 

         quicksort(a,0, length-1);                 //先进行排序,求得最小排列

         while(1)

         { 

                  printall(a,length);         //打印当前队列

                  int i,j; 

 

                  for(i=length-2; i>=0; --i)                 //找到替换点

                 

                          if(a[i]<a[i+1])break;      

                          else  if(i==0) return; 

                  } 

                  for(j=length-1;j>i; --j)            //从后往前找第一个比替换数大的数

                  

                          if(a[j]>a[i])break; 

                  } 

                   swap(a,i,j);                              //交换替换点

                  reverse(a,i+1,length-1);       //反转替换点之后的数

         } 

 

二:跳台阶问题

    题目:一个台阶总共有n 级,如果一次可以跳1 级,也可以跳2 级。求总共有多少总跳法,并分析算法的时间复杂度。

    首先考虑最简单的情况。如果只有1级台阶,那显然只有一种跳法。如果有2级台阶,那就有两种跳的方法了:一种是分两次跳,每次跳1级;另外一种就是一次跳2级。

    现在我们再来讨论一般情况。我们把n级台阶时的跳法看成是n的函数,记为f(n)。当n>2时,第一次跳的时候就有两种不同的选择:一是第一次只跳 1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1);另外一种选择是第一次跳2级,此时跳法数目等于后面剩下的n-2级台阶的跳 法数目,即为f(n-2)。因此n级台阶时的不同跳法的总数f(n)=f(n-1)+(f-2)。

       /     1                    n=1
f(n)=          2                     n=2
        \     f(n-1) +f(n-2)      n>2

    这样上述问题就是平常所熟知的Fibonacci数列问题。

 

三:奇偶排序问题

    问题描述:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)。

 

    分析:维护两个指针,一个指针指向数组的第一个数字,向后移动;一个指针指向最后一个数字,向前移动。如果第一个指针指向的数字是偶数而第二个指针指向的数字是奇数,我们就交换这两个数字。

    代码实现:

    while(pBegin < pEnd) 

    { 

        if(!isEven(*pBegin))     

        { 

            pBegin ++; 

            continue; 

        } 

        if(isEven (*pEnd))        

        { 

            pEnd --; 

            continue; 

        }  

        int temp = *pBegin; 

        *pBegin = *pEnd; 

        *pEnd = temp; 

    } 

 

(http://blog.csdn.net/v_july_v/article/details/6879101)

(http://www.cnblogs.com/bakari/archive/2012/08/02/2620826.html)

(http://blog.csdn.net/e3399/article/details/7543861)

 

转载于:https://www.cnblogs.com/gqtcgq/p/7247171.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值