Permutation

  • Permutation全排列

给定当前排列,如何得到下一个排列

1. 对于排列a[1...n],找到所有满足a[k] < a[k+1] 的k的最大值,如果这样的k不存在,则说明当前排列已经是a的所有排列中字典序最大者,所有排列输出完毕。

2.a[k+1...n]中,寻找满足这样条件的元素l,使得在所有a[l]>a[k]的元素中,a[l]取得最小值。也就是说a[l]>a[k],但是小于所有其他大于a[k]的元素。

3. 交换a[l]与a[k].

4. 对于a[k+1...n],反转该区间内元素的顺序。这样就得到了a[1...n]在字典序中的下一个排列。
public class Solution {
    public void nextPermutation(int[] nums) {
        if(nums==null || nums.length <= 1)
            return;
        int i=nums.length-2;
        while(i>=0 && nums[i]>=nums[i+1]) i--;
        if(i>=0){
            int j = nums.length-1;
            while(nums[j]<=nums[i])j--;
            sw(nums,i,j);
        }
        re(nums,i+1,nums.length-1);
    }

    public void sw(int[] nums,int i,int j){
        int tmp = nums[i];
        nums[i]=nums[j];
        nums[j]=tmp;
    }
    public void re(int[] nums,int i,int j){
        while(i<j)
            sw(nums,i++,j--);
    }
}
STL中有next_permutation这个函数

找到前一个排列的算法和找下一个的算法类似


给定n,选择n中的m个数进行全排列,并输出。例如n=3 m=1 输出为1 2 3
递归,搜索


#include<cstdio>
#include<cstring>

int visit[10];
int a[10];
int n,m;

void permutation(int i)
{
    int j,k;
    if(i>m)
    {
        for(k=1;k<=m;++k)
            printf("%d",a[k]);
        printf("\n");
    }
    else
    {
        for(j=1;j<=n;++j)
        {
            if(visit[j]==0)
            {
                visit[j]=1;
                a[i]=j;
                permutation(i+1);
                visit[j]=0;
            }
        }
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(visit,0,sizeof(int));
        permutation(1);
    }
    return 0;
}

给定一个排序,输出在全排列中排第几 或者 给定n,输出全排列中第n个排列

康托展开公式

X=an*(n-1)!+an-1*(n-2)!+…+ai*(i-1)!+…+a2*1!+a1*0!
其中a[i]为当前未出现的元素中是排在第几个(从0开始)
适用范围:没有重复元素的全排列

题目:找出第16个n = 5的序列(12345)
首先第十六个也就是要前面有15个数

1. 根据第一行的那个全排列公式,15 / 4! = 0 …15  =》  有0个数比他小的数是1,所以第一位是1
2. 拿走刚才的余数15,用15 / 3! = 2 …3   =>  剩下的数里有两个数比他小的是4(1已经没了),所以第二位是4
3. 拿走余数3, 用 3 / 2! = 1 …1   =》  剩下的数里有一个数比他小的是3,所以第三位是3
4. 拿走余数1, 用 1/  1! = 1 …0    =>  剩下的数里有一个数比他小的是 5(只剩2和5了),所以第四位是5

所以排列是 1,4,3,5,2

第二类题 :已知是n = 5,求14352是它的第几个序列?(同一道题)
用刚才的那道题的 反向思维 :

1. 第一位是1,有0个数小于1,即0* 4!
2. 第二位是4,有2个数小于4,即2* 3!
3. 第三位是3,有1个数小于3,即1* 2!
4. 第四位是5,有1个数小于5,即1* 1!
5. 第五位是2,不过不用算,因为肯定是0

所以14352是 n = 5的第 0 + 12 + 2 + 1 + 0 = 15    + 1(求的是第几个,所以要加一) = 16
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值