代码改变世界

面试题之括号匹配分析( 出栈序列是否合法,给定一个入栈序列,求所有可能的出栈序列等等)

2013-10-04 21:52  youxin  阅读(2726)  评论(0编辑  收藏  举报

题目:括号匹配分析

给定字符串,输出括号是否匹配,例如,

  1. "()" yes;

  2. ")(" no;

  3. "(abcd(e)" no;

  4. "(a)(b)" yes。

要求必须用递归写,整个实现不可以出现一个循环语句。

分析

这个题目很多同学都见过了,如果没有后面的条件,会张口就说就来用栈来实现,时间复杂度O(n),空间复杂度O(n)。这个是很好的一个解答,没有 问题的。但是我们在做面试题,准备面试的过程中,每一个题目都不应该仅仅局限于某一个方法。应该尝试更多的思路,尽管有些思路的时间、空间复杂度并不是很 好,但是可以带来变化,举一反三,这才是真正的收获。

这个题要求了,只目能使用递归并且不能出现循环语句。这个时候,我们应该如何处理呢?其实告诉了大家递归,就比较好想了:怎么定义好问题和子问题。

如果字符串中的括号是匹配的,则'('的数量和')'的数量是相等的,反之是不相等的。这样,在递归的过程中,可以保存一个变量,用来记录'('的 数量和')'的数量是否匹配。这样定义递归问题f(p,count),表示当前字符p之前的字符串中'('的数量和')'的数量的匹配情况,p表示指向当 前字符的指针。初始的时候,f(p, 0),递归的过程如下:

 

  1. 如果p为空,则考察count是否为0,如果为0,则匹配;如果不为0,则不匹配;

  2. 如果不为空,则考察当前字符p,如果p='(',则递归调用f(p++, count++);如果p=')',则递归调用f(p++, count--)。如果p是其他的字符,并不是'('和')',则递归调用f(p++, count),count不变,继续考虑下一次字符。其中需要检查和保证count>=0.

     

其实,递归的问题有的时候不是那么好像的,需要大家不断的练习。如果不采用count来记录括号匹配的情况,这个题目的递归也不好想。

基于栈的代码:

bool isMatched(const char *str)
{
    stack<char> s;
    while(*str)
    {
        if(*str=='(')
        {
            s.push('(');
        }
        else if(*str==')')
        {
            if(!s.empty())//这里很重要,保证了如果输入)(,就直接退出
            {
                s.pop();

            }
            else
            {
                return false;
            }
        }
        str++;
    }
    return s.empty();
}

递归的代码:下面是我刚开始写的,有什么错误吗?

bool isMatchedRec(char *p,int count)
{
    if(*p=='\0')
    {
        return count==0;//如果p为空,则考察count是否为0,如果为0,则匹配;如果不为0,则不匹配;
    }
    else
    {
        if(*p=='(')
        {
            //return isMatchedRec(p++,count++); 错误,在递归内要写前缀++,不要写后缀,否则无穷递归。
             
            return isMatchedRec(++p,++count);
        }
        else if(*p==')')
        {
            return isMatchedRec(++p,--count);
        }
        else
        {
            return isMatchedRec(++p,count);
        }
    }
}

错误在哪里;

假设我们输入“)(”,返回的还是true。

原因是没有没有检查count>=0.

正确的代码:

bool isMatchedRec(char *p,int count)
{
    if(*p=='\0')
    {
        return count==0;//如果p为空,则考察count是否为0,如果为0,则匹配;如果不为0,则不匹配;
    }
    else
    {
        if(count>=0)
        {
            if(*p=='(')
            {
                 
             
                return isMatchedRec(++p,++count);
            }
            else if(*p==')')
            {
                return isMatchedRec(++p,--count);
            }
            else
            {
                return isMatchedRec(++p,count);
            }
        }
        else 
            return false;
       
    }
}

可以把上面代码再简化下:

bool isMatchedRec2(const char* s,int count)
{
    if(count<0)
        return false;

    if(*s=='\0')
    {
        return count==0;
    }
    else
    {
        if(*s=='(')
            count++;
        else if(*s==')')
            count--;
    }

    return isMatchedRec2(++s,count);
}

 

参考:http://blog.csdn.net/buaa_shang/article/details/11726619

扩展问题;

假设字符串中包含{,[,( 三种括号,请判断是否匹配。

http://blog.chinaunix.net/uid-28458801-id-3664897.html

 

bool isPair(char a,char b)
{
    bool flag=true;
    if(a=='{' && b=='}')
        flag=true;
    else if(a=='[' && b==']')
        flag=true;
    else if(a=='(' && b==')')
        flag=true;
    else
        flag=false;

    return flag;
}

bool isMatched(const char *str)
{
    stack<char> s;
    while(*str)
    {
        if(*str=='{' || *str=='[' || *str=='(' )
        {
            /*if( (s.top()=='{') || (s.top()=='['&&*str!='{') && (s.top()=='('&& *str=='(') )
                s.push(*str);
            else
                return false;
                */
            s.push(*str);

        }
        else if(*str=='}' || *str==']' || *str==')' )
        {
            if(!s.empty())//这里很重要,保证了如果输入)(,就直接退出
            {
                if(isPair(s.top(),*str))
                {
                    s.pop();
                }
                else
                {
                    return false;
                }


            }
            else
            {
                return false;
            }
        }
        str++;
    }
    return s.empty();
}
 

 

题目扩展

        给你一个字符串,里面只包含"(",")","[","]","{","}"几种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
        例如:
        []是匹配的,所需括号个数为 0;([])[]是匹配的, 所需括号个数为 0;((]是不匹配的, 所需最少括号个数为 3;([)]是不匹配的,所需最少括号个数为 2.

 

        这道变种题大多数人的解题思路都是动态规划,思路如下。不知道大家有没有好的别的方法,求教。

     1)用 dp[i][j] 表示从位置 i  到字符位置 j 所需的最少括号数。假定字符串是 “[ ( )”, 那么 dp[0][0] = dp[1][1]  = dp[2][2] = 1。

     

    2)如果我们要算dp[i][j+1], 那么,最坏的情况是使得没有被匹配的括号数增加了,即 dp[i][j+1] 最多为 min( dp[i][j] + 1, dp[i+1][j+1] + 1). 但是,这可能不是我们想要的答案,因为在刚才的例子里,即:假定字符串是 “[ ( )”, 那么 dp[0][1] = dp[0][0] + 1= 2, 但是 dp[1][2] 却不等于 dp[1][1] + 1.

    

    3)那么,什么情况下dp[i][j+1] = dp[i][j] + 1?只有当 字符串里从i 到 j 没有任何字符与第 j + 1 个字符匹配的时候。但是,如果存在和第 j + 1 个字符匹配的情况,问题就不一样了。

 

    4)假设在i 到 j 之间存在一个字符(比如在位置 k)与第 j + 1 个字符匹配,那么我们相当于把原来的字符串分成了两个部分dp[i][k-1] 和 dp[k+1][j], 因为第k 个 和 j + 1 个字符已经匹配掉了。而且,我们不会再考虑 i 到 k - 1 的字符会和 k + 1 到 j 之间的字符匹配的情况,因为我们已经把这两个部分完全分开了。话句话说 dp[i][j+1] = min(min( dp[i][j] + 1, dp[i+1][j+1] + 1),  dp[i][k-1] + dp[k+1][j]).

#include<iostream>
#include<string>
#include<memory.h>
using namespace std;
bool is(char a, char b){
    if(a == '(' && b == ')')
        return 1;
    if(a == '[' && b == ']')
        return 1;
    if(a == '{' && b == '}')
        return 1;
    return 0;
}
int main(){
    //dp[i][j] 表示从第i位至第j位的最小匹配长度
    int t, i, j, k, dp[105][105];
    cin >> t;
    while(t--){
        string s;
        cin >> s;
        memset(dp, 0, sizeof(dp));
        for(i = 0; i <= s.length(); ++i){
            dp[i][i] = 1;
        }
        for(i = 2; i <= s.length(); ++i){
            for(j = i - 1; j >= 1; --j){
                dp[j][i] = dp[j][i - 1] + 1;
                for(k = j; k < i; ++k){
                    if(is(s[k - 1], s[i - 1])){
                        dp[j][i] = min(dp[j][i], dp[j][k - 1] + dp[k + 1][i - 1]);
                    }
                }
            }
        }
        cout << dp[1][s.length()] << endl;
    }
    return 0;
}

 改写的更容易看懂 的代码:

dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j])k [i,j)

bool isPair(char a,char b)
{
     if(a == '(' && b == ')')
        return 1;
    if(a == '[' && b == ']')
        return 1;
    if(a == '{' && b == '}')
        return 1;
    return 0;
}

int match(int dp[100][100],char s[])
{ 
    for(int i=0;i<100;i++)
        for(int j=0;j<100;j++)
            dp[i][j]=0;

    int len=strlen(s);
    for(int i=0;i<=len;i++)
        dp[i][i]=1;

    for(int j=2;j<=len;j++)
    {
        for(int i=j-1;i>=1;i--) //i从1开始,说明dp[0]不存
        {
            dp[i][j]=dp[i][j-1]+1;
            for(int k=i;k<j;k++)
            {
                if(isPair(s[k-1],s[j-1]))
                {
                    dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j-1]);
                }
            }
         
        }
    }
    return dp[1][len];
}

 递归版:

 //递归版
#include<stdio.h>
#include<string.h>

const int inf = 0x0fffffff;
#define min(x, y)(x < y ? x : y)
#define low(x, y)((x == '(' && y == ')') || (x == '[' && y == ']'))
char str[110];
int dp[110][110];
int fun(int x,int y)
{
    if(dp[x][y] != -1)
        return dp[x][y];
    if(x > y)return 0;
    if(x == y)return 1;
    int ans = inf;
    if(low(str[x], str[y]))
        ans = min(ans, fun(x + 1, y - 1));
    for(int i = x;i < y; ++ i)
        ans = min(ans, fun(x, i) + fun(i + 1, y));
    dp[x][y] = ans;
    return ans;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%s", str);
        int len = strlen(str);
        memset(dp, -1, sizeof(dp));
        printf("%d\n", fun(0, len - 1));
    }
}

参考:http://blog.acmj1991.com/?p=1142

http://www.dewen.org/q/8653/%E4%B8%80%E4%B8%AA%E6%8B%AC%E5%8F%B7%E5%8C%B9%E9%85%8D%E7%9A%84%E6%89%A9%E5%B1%95%E9%97%AE%E9%A2%98

另一题:

输入括号的数目,输出括号的各种合法匹配样式

输入 2

输出 

 (())

()()

据说这是一道某公司的面试题,我们先来分析一下。括号匹配有合法有的不合法 如 (()))( 这样就不是合法的匹配样式。为了避免这种情况的出现,记录当前左括号的个数和右括号的个数,使右括号的个数不大于左括号的个数。主要思想类似于0-1背包问题,当进行到某一步的时候 有两种方法:放'(' 和 放 ')'

void matching(int left,int right,int sum,vector<char> bracket)
{
    if (left==sum&&right==sum)  //如果左边和右边都为要匹配的个数,则输出结果
    {
        vector<char>::iterator iter=bracket.begin();
        for ( ;iter!=bracket.end();iter++)  
        {
            cout<<*iter<<' ';
        }
        cout<<endl;
        return ;
    }
    if (left<=sum)
    {
        bracket.push_back('(');    //放入左括号,然后递归
        matching(left+1,right,sum,bracket);
        bracket.pop_back();        //递归后弹出左括号
    }
    
    if (left>right&&left<=sum)
    {
        bracket.push_back(')');
        matching(left,right+1,sum,bracket);
        bracket.pop_back();
    }
}
int main(int argc, char* argv[])
{
    vector<char> bracket;    //记录当前的匹配样式
    int num;
    cin>>num;                //输入括号的个数 
    matching(0,0,num,bracket);
    return 0;
}

我最开始想的是回溯法,应该和八皇后问题思路一致。但这个程序不是。上面递归程序不好理解。

可以举个例子:sum=3时,

最开始一值是运行第二个递归:

(((,

接着:

放入一个),接着递归,又放入一个),又放入); 最后变成了:

((()));

 输出这个之后。

 给定一个入栈序列,求所有可能的出栈序列

有2n个人排成一队进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票可找零,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?(将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈)。

对于这个例子,剧院要想总有零钱可找,那么目前进入剧院的人数中,揣着10元钞票的人数必须少于等于揣着5元钞票的,不然肯定在某个人那出现没零钱找的情况。

现在回到正题上来对于一个给定入栈序列,怎么求它的出栈序列呢?

我们可以把入栈记为1,出栈记为0.那么前缀子序列中1的个数必须大于等于0的个数,即入栈次数要大于等于出栈次数,如1 1 0 1 0 0,它的任意前缀序列中1的个数是大于等于0的个数的。

我们来看个例子:对于1 2 3这个入栈序列,1 1 0 1 0 0就是一个入栈出栈序列,第一个1代表元素1入栈,然后第二个1代表元素2入栈,然后第三个是0,代表出栈,即元素2出栈,然后第四个是1,代表元素3入栈,然后第五个是0,代表出栈,即元素3出栈,然后第六个是0,代表元素1出栈。最后1 1 0 1 0 0就代表了出栈序列2 3 1。

那么现在的问题就转换为如何求出所有符合条件的0 1序列了。其实这和以下问题相同:给定括号对数,输出所有符合要求的序列。如2对括号,输出有()()或者(())两种。1可以看成'(',0可以看成‘)’。

下面贴上本人的程序,并给出详细注释。

#include <iostream>
#include <vector>
using namespace std;


void func(vector<char>kind,int count[],int n)
{
    if(count[0]>=1)
    {
        kind.push_back('(');
        count[0]--;
        func(kind,count,n);
        count[0]++;
        kind.pop_back();
    }
    if((count[1]>=1) && (count[1]>count[0]))
    {
        kind.push_back(')');
        count[1]--;
        func(kind,count,n);
        count[1]++;
        kind.pop_back();
    }
    if(kind.size()==2*n)
    {
        vector<char>::iterator iter;
        for(iter=kind.begin();iter!=kind.end();iter++)
        {
            cout<<(*iter)<<" ";
        }
        cout<<endl;
    }
}


int main()
{
    int n;
    cout << "please input the number of ():" << endl;
    cin>>n;
    int count[2]={n-1,n};
    vector<char>kind;
    kind.push_back('(');
    func(kind,count,n);
    return 0;
}

count[0]存着左括号数目,count[1]存着右括号数目。一开始kind中压入左括号,因为第一个肯定是左括号。然后count数组初始化为n-1个左括号,n个右括号。然后我们递归的处理。如果剩余左括号数count[0]大于0,就可以把左括号压栈。而对于右括号,栈中左括号个数必须多于右括号个数,也就是剩余右括号个数大于左括号个数,即count[1]>count[0]时,才能将右括号压栈。如果栈中元素个数达到2n时,就把栈中元素输出。

下面贴出出栈序列代码,几乎和上面相同。

#include <iostream>
#include <stack>
#include <vector>
using namespace std;


int number=0;
void func(vector<int>kind,int count[],int n,int A[])
{
    if(count[0]>=1)
    {
        kind.push_back(1);
        count[0]--;
        func(kind,count,n,A);
        count[0]++;
        kind.pop_back();
    }
    if((count[1]>=1) && (count[1]>count[0]))
    {
        kind.push_back(0);
        count[1]--;
        func(kind,count,n,A);
        count[1]++;
        kind.pop_back();
    }
    if(kind.size()==2*n)
    {
        vector<int>::iterator iter;
        stack<int>stk;
        int j=0;
        for(iter=kind.begin();iter!=kind.end();iter++)
        {
            //cout<<(*iter)<<" ";
            if(1==(*iter))
            {
                stk.push(A[j]);
                j++;
            }
            else
            {
                cout<<stk.top()<<" ";
                stk.pop();
            }
        }
        number++;
        cout<<endl;
    }
}


int main()
{
    int n,i;
    cout << "please input the number:" << endl;
    cin>>n;
    int A[n];
    cout << "please input the push sequence:" << endl;
    for(i=0;i<n;i++)
    {
        cin>>A[i];
    }
    int count[2]={n-1,n};
    vector<int>kind;
    kind.push_back(1);

    cout<<"the result is:"<<endl;
    func(kind,count,n,A);
    cout<<"total:"<<number<<endl;
    return 0;
}

参考:http://blog.csdn.net/zz198808/article/details/7585385

一篇文章:

#include<iostream>
#include<stack>
using namespace std;

static int counter;

void outprint(stack<int> q){
    while (q.size() != 0)  {
        cout << q.top() << "-> ";
        q.pop();
    }
    cout << endl;
    counter++;
    return;
}

//q 存放入栈序列
//stk 用于模拟入栈过程
//output 用于存放可能的出栈序列
void allPopSeq(stack<int> q,stack<int> stk,stack<int> output){
    if((q.size() == 0)&&(stk.size()==0)&&(output.size() == 5)) {
        outprint(output);
        return;
    }
    if(q.size()!=0){//入栈
        int v = q.top();   
        stk.push(v);   
        q.pop();
        allPopSeq(q,stk,output);
        stk.pop();
        q.push(v);//回溯恢复
    }
    if(stk.size()!=0) //出栈
    {
        int v = stk.top();
        stk.pop();
        output.push(v);
        allPopSeq(q,stk,output);
        output.pop();
        stk.push(v);//回溯恢复
    }
    return;
}
int main()
{
    int arr[5] = { 1, 2, 3, 4, 5 };
    stack<int> stkValues;
    stack<int> stkOutput;
    stack<int> tmp;
    int i;
    for (i = 0; i != 5; ++i){
        stkValues.push(arr[i]);
    }
    allPopSeq(stkValues, tmp, stkOutput);
    cout << counter << endl;
}
 

http://www.cnblogs.com/fxplove/articles/2500898.html

程序员面试题精选100题(24)-栈的push、pop序列[数据结构]  

题目:输入两个整数序列。其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序。为了简单起见,我们假设push序列的任意两个整数都是不相等的。

比如输入的push序列是1、2、3、4、5,那么4、5、3、2、1就有可能是一个pop系列。因为可以有如下的push和pop序列:push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop,这样得到的pop序列就是4、5、3、2、1。但序列4、3、5、1、2就不可能是push序列1、2、3、4、5的pop序列。

分析:这到题除了考查对栈这一基本数据结构的理解,还能考查我们的分析能力。

这道题的一个很直观的想法就是建立一个辅助栈,每次push的时候就把一个整数push进入这个辅助栈,同样需要pop的时候就把该栈的栈顶整数pop出来。

我们以前面的序列4、5、3、2、1为例。第一个希望被pop出来的数字是4,因此4需要先push到栈里面。由于push的顺序已经由push序列确定了,也就是在把4 push进栈之前,数字1,2,3都需要push到栈里面。此时栈里的包含4个数字,分别是1,2,3,4,其中4位于栈顶。把4 pop出栈后,剩下三个数字1,2,3。接下来希望被pop的是5,由于仍然不是栈顶数字,我们接着在push序列中4以后的数字中寻找。找到数字5后再一次push进栈,这个时候5就是位于栈顶,可以被pop出来。接下来希望被pop的三个数字是3,2,1。每次操作前都位于栈顶,直接pop即可。

再来看序列4、3、5、1、2。pop数字4的情况和前面一样。把4 pop出来之后,3位于栈顶,直接pop。接下来希望pop的数字是5,由于5不是栈顶数字,我们到push序列中没有被push进栈的数字中去搜索该数字,幸运的时候能够找到5,于是把5 push进入栈。此时pop 5之后,栈内包含两个数字1、2,其中2位于栈顶。这个时候希望pop的数字是1,由于不是栈顶数字,我们需要到push序列中还没有被push进栈的数字中去搜索该数字。但此时push序列中所有数字都已被push进入栈,因此该序列不可能是一个pop序列。

也就是说,如果我们希望pop的数字正好是栈顶数字,直接pop出栈即可;如果希望pop的数字目前不在栈顶,我们就到push序列中还没有被push到栈里的数字中去搜索这个数字,并把在它之前的所有数字都push进栈。如果所有的数字都被push进栈仍然没有找到这个数字,表明该序列不可能是一个pop序列。

基于前面的分析,我们可以写出如下的参考代码:

#include <stack>

/////////////////////////////////////////////////////////////////////////////
// Given a push order of a stack, determine whether an array is possible to 
// be its corresponding pop order
// Input: pPush   - an array of integers, the push order
//        pPop    - an array of integers, the pop order
//        nLength - the length of pPush and pPop
// Output: If pPop is possible to be the pop order of pPush, return true.
//         Otherwise return false
/////////////////////////////////////////////////////////////////////////////
bool IsPossiblePopOrder(const int* pPush, const int* pPop, int nLength)
{
      bool bPossible = false;

      if(pPush && pPop && nLength > 0)
      {
            const int *pNextPush = pPush;
            const int *pNextPop = pPop;

            // ancillary stack
            std::stack<int> stackData;

            // check every integers in pPop
            while(pNextPop - pPop < nLength)
            {
                  // while the top of the ancillary stack is not the integer 
                  // to be poped, try to push some integers into the stack
                  while(stackData.empty() || stackData.top() != *pNextPop)
                  {
                        // pNextPush == NULL means all integers have been 
                        // pushed into the stack, can't push any longer
                        if(!pNextPush)
                              break;

                        stackData.push(*pNextPush);

                        // if there are integers left in pPush, move 
                        // pNextPush forward, otherwise set it to be NULL
                        if(pNextPush - pPush < nLength - 1)
                              pNextPush ++;
                        else
                              pNextPush = NULL;
                  }

                  // After pushing, the top of stack is still not same as 
                  // pPextPop, pPextPop is not in a pop sequence
                  // corresponding to pPush
                  if(stackData.top() != *pNextPop)
                        break;

                  // Check the next integer in pPop
                  stackData.pop();
                  pNextPop ++;
            }

            // if all integers in pPop have been check successfully, 
            // pPop is a pop sequence corresponding to pPush 
            if(stackData.empty() && pNextPop - pPop == nLength)
                  bPossible = true;
      }

      return bPossible;
}

http://zhedahht.blog.163.com/blog/static/25411174200732102055385/

 或者判断出栈序列是否合法

输入两个整形序列,*put,*out,分别表示入栈和出栈,判断出栈是否符和入栈要求。

假设入栈为 首先1,2,3,4,5.出栈顺序为4,3,5,1,2
分析:要得到4,则需将1,2,3,4全部入栈,然后pop得到4,输出3,因为栈顶元素即为3,直接输出即可。如果要得到5,需要将入栈队列中的5压入栈,然后输出。此时入栈队列已经为空。栈顶元素为2,底为1.此时需要输出1,但是要先输出2,错误,则此出栈顺序不合理。
 
即如果元素在栈顶,直接pop得到,若不在栈顶,需要从入栈队列找到她,一直入栈,然后在pop。否则无法顺利。
 
代码: 这个代码写的还可以
 bool Judge(int *put,int *out,int len)
{
   bool val=false;
   if(put&&out&&len>0)
   {
     int *p=put;
     int *q=out;
     stack<int> a;
    while(q-out<len)
   {  
        while(a.empty()||*q!=a.top())    //如果栈为空或者栈顶元素不等于*q  则需寻找
        {
          if(!p)
           break;
          a.push(*p);
          if(p-put<len)   //判断入栈队列是否含有元素
             p++;
          else
             p=NULL;
 
          }
          if(*q!=a.top())  //全部入栈后还是不等
              break;
          a.pop();
          q++;    //判断下一个
    }
     if(a.empty()&&(q-out==len))
             val=true;
   }
  return     val;
}
 
 
扩展,给出一组数字为出栈队列,求其可能的入栈队列。
 
分析:可以根据这组数字,全排列出所有组合,然后每一个组合利用上面的函数判别即可,如果true 即输出。
 
代码:
    void fun(int *a,int *begin,int n,int *b)    //全排列求解
    {
     if(begin-a==n)
     {
        if(Judge(a,b,n)
             for(int i=0;i<n;i++)
              cout<<a[i]<<"  满足条件!!"<<endl;
     }
    else
    {
       for(int *temp=beign;temp-a<n;temp++)
           {
            int val=*begin;
                *begin=*temp;
                *temp=val;
                fun(a,begin+1,n,b);
                 *temp=*begin;
                *begin=val;
             }
     }
      
 }
 
void Show(int *b,int n)
{
  int *a=new int[n];
  for(int i=0;i<n;i++)
       a[i]=n[i];
    fun(a,a,n,b);
   delete []a;
}
 
 
int main()
{
    int b[]={4,5,3,2,1};
    Show(b,5);
}

 参考:

http://blog.163.com/m13591120447_1/blog/static/21637918920132270746190/

http://blog.sina.com.cn/s/blog_4ac9f56e01014vcs.html

 http://blog.chinaunix.net/uid-21712186-id-1818123.html