60. Permutation Sequence&字符串排列&8.7Permutations without Dups

The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "321"

Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.

我的方法从高位到低位逐位确定数字。

以图例n=3进行说明:

构建数组v={1,2,3}

确定最高位:

ind=(k-1)/2

注:分母2是指每个最高位持续的排列数。由于除了最高位之外还有n-1=2位,一共可以出现2!种排列。

ind指的是所求的第k个排列会落在哪一个最高位的覆盖范围内。

k==1,2时,ind==0,最高位为v[ind]==1

k==3,4时,ind==1,最高位为v[ind]==2

k==5,6时,ind==2,最高位为v[ind]==3

其余数位如上思路逐位确定。

注意:

1、k的更新。k-=ind*fac(n-1),例如当k=1和2时,第二次的k就不变,当k=3或4时,第二次的k就应该等于1或2,也就是跳过以1开头的排列后,索要求得排列是第1个或第2个。(这块儿还有些绕,理解的不够)

2、vector<int> v的更新。将已经放好的数字,用它后面未放置的数字覆盖,然后将vector的最后一个元素pop掉。

//http://www.cnblogs.com/ganganloveu/p/4156188.html
//http://www.cnblogs.com/friends-wf/p/3676848.html

class Solution {
public:

    int fac(int n)
    {
        int ret = 1;
        while(n)
        {
            ret *=n;
            n--;
        }
        return ret;
    }
    string getPermutation(int n, int k) {
        
        string ret;
        vector<int> v(n);
        
        for(int i = 0;i< n;i++)
        {
            v[i] = i + 1;
        }
        
        while(n)
        {
            int ind = (k-1)/fac(n-1);
            ret+=(v[ind]+'0');
            k-=ind*fac(n-1);
            for(int i = ind+1;i<n;i++)
            {
                v[i-1] = v[i];
            }
            v.pop_back();
            n--;
        }
        return ret;
        
        
    }
};


与组合数一样,简单构造法(Base Case and Build approach )非常管用。假设字符串S,以字符序列表示。

方法1:从前n-1个字符的排列构造

基本情况:第一个字符的排列

的排列只有一种,即

情况:的排列


情况:的 排列



情况:的排列

这是第一个有趣的情况。我们如何从的所有排列得到的所有排列?

的每一个排列代表的一个排序。例如,表示排序

因此,如果我们拿出的所有排列,并将加入到所有可能的位置,我们就可以得到的所有排列。




class Permutation {
public:
    vector<string> getPermutation(string A) {
        // write code here
        vector<string> ret;
        if(A.length() == 0)
        {
            string tmp="";
            ret.push_back(tmp);
            return ret;
        }
        
        char firstCh = A[0];
        string remainderA = A.substr(1);
        vector<string> remainderRet = getPermutation(remainderA);
        for(vector<string>::iterator it = remainderRet.begin();it!= remainderRet.end();++it)
        {
            for(int i = 0;i<=it->length();++i)
            {
                string tmp(*it);
                tmp.insert(i,1,firstCh);
                ret.push_back(tmp);
                
            }
        }
        
        sort(ret.begin(),ret.end(),greater<string>());
        return ret;
        
    }
};


全排列,昨天正好刚在组合数学课上学了,自己尝试着写了一把,自己跑用例,结果是正确的,但是oj一直超时。代码如下

class Solution {
public:
    vector<vector<int> > permute(vector<int> &num) {
    vector<vector<int> > res;
    if(num.empty())
        return  res;
    if(num.size() == 1)
    {
        res.push_back(num);
        return res;
    }
    
     
    sort(num.begin(),num.end());
    res.push_back(num);
    vector<int> tmp = num;
    reverse(tmp.begin(),tmp.end());

    while(num != tmp)
    {
        nextPermute(num);
        res.push_back(num);
    }
    
    return res;
    }
    
    void nextPermute(vector<int> num)
    {
        int iMax;
    for(int i = num.size() - 1;i >= 1;i--)
        if(num[i-1] < num[i])
            {
                iMax = i;
                break;
            }
    int jMax;
    for(int j = num.size() -1 ;j >= iMax;j--)
        if(num[iMax -1] < num[j])
            {
                jMax = j;
                break;
            }
    
    swap(num[iMax -1],num[jMax]);
    
    reverse(num.begin()+iMax,num.end());
    }
};

修正后的代码,ac

class Solution {
public:
    vector<vector<int> > permute(vector<int> &num) {
    vector<vector<int> > res;
   
    
     
    sort(num.begin(),num.end());
    vector<int> tmp = num;
    
    
    
   

    do{
        res.push_back(num);
        nextPermutation(num);
    }while(num != tmp);
    
    return res;
    }
    
     void nextPermutation(vector<int> &num) {
    int iMax = -1;
    for(int i = num.size() - 1;i >= 1;i--)
        if(num[i-1] < num[i])
        {
            iMax = i;
            break;
        }
    int jMax = -1;
    for(int j = num.size() -1 ;j >= iMax;j--)
        if(num[iMax -1] < num[j])
        {
            jMax = j;
            break;
        }
    
    
    if(iMax != -1 and jMax != -1)
    {
        swap(num[iMax -1],num[jMax]);
        
        reverse(num.begin()+iMax,num.end());
    }
    //f such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
    else
        reverse(num.begin(),num.end());
    
    
}
    
    
    
};




直接调用库函数next_permutation(),一次ac

class Solution {
public:
    vector<vector<int> > permute(vector<int> &num) {
    vector<vector<int> > res;
   
    
     
    sort(num.begin(),num.end());
    
   

    do{
        res.push_back(num);
    }while(next_permutation(num.begin(),num.end()));
    
    return res;
    }
    
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值