zoukankan      html  css  js  c++  java
  • 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 == '')

             {

                 printf("%s ", pStr);

             }

             else

             {

                for(pCh = pBegin; *pCh != ''; ++ 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)

     

  • 相关阅读:
    第三发
    第二发
    第一发
    要看的算法
    haxe坑
    TCP/IP协议三次握手与四次握手流程解析(转)
    Android动态类生成预加载-dexmaker使用
    Java中ArrayList 、LinkList区别
    Java解析YAML和Android解析YAML
    Java sax、dom、pull解析xml
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/7247171.html
Copyright © 2011-2022 走看看