康托展开公式与全排列应用
时间:2022-07-24
本文章向大家介绍康托展开公式与全排列应用,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
康托展开公式
X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!
怎样知道其中一种排列是有序序列中的第几个?
康托展开. {1...n}的全排列由小到大有序,s[]为第几个数
{1,2,3,4,...,n}的排列总共有n!种,将它们从小到大排序,怎样知道其中一种排列是有序序列中的第几个?
如 {1,2,3} 按从小到大排列一共6个:123 132 213 231 312 321。想知道321是{1,2,3}中第几个大的数。
这样考虑:
- 第一位是3,小于3的数有1、2 。所以有2*2!个。
- 再看小于第二位,小于2的数只有一个就是1 ,所以有1*1!=1
- 所以小于32 的{1,2,3}排列数有22!+11!=5个。所以321是第6个大的数。
22!+11!是康托展开。
康托逆运算
康托展开的逆运算. {1...n}的全排列,中的第k个数为s[] {1,2,3,4,5}的全排列已经从小到大排序,要找出第16个数:
1. 首先用16-1得到15
2. 用15去除4! 得到0余15
3. 用15去除3! 得到2余3
4. 用3去除2! 得到1余1
5. 用1去除1! 得到1余0
6. 有0个数比它小的数是1所以第一位是1
7. 有2个数比它小的数是3,但1已经在之前出现过了所以是4
8.有1个数比它小的数是2,但1已经在之前出现过了所以是3
9.有1个数比它小的数是2,但1,3,4都出现过了所以是5
最后一个数只能是2
所以这个数是14352
代码
public class KangTuo {
/**
* 康托展开:X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!
* ai为整数,并且0<=ai<i(1<=i<=n)
*/
private int fac[] = {1,1,2,6,24,120,720,5040,40320}; //i的阶乘为fac[i]
/*
* 康托展开. {1...n}的全排列由小到大有序,s[]为第几个数
* {1,2,3,4,...,n}的排列总共有n!种,将它们从小到大排序,怎样知道其中一种排列是有序序列中的第几个?
*
* 如 {1,2,3} 按从小到大排列一共6个:123 132 213 231 312 321。想知道321是{1,2,3}中第几个大的数。
* 这样考虑:第一位是3,小于3的数有1、2 。所以有2*2!个。再看小于第二位,小于2的数只有一个就是1 ,所以有1*1!=1 所以小于32
*
* 的{1,2,3}排列数有2*2!+1*1!=5个。所以321是第6个大的数。2*2!+1*1!是康托展开。
*/
public int KangTuo(int n, int s[])
{
int sum = 0;
for(int i = 0; i < n; i++){
int t = 0;
for(int j = i+1; j < n;j++){
if(s[i] > s[j]){
t++;
}
}
sum += t *fac[n-i-1];
}
return sum+1;
}
/*
* 康托展开的逆运算. {1...n}的全排列,中的第k个数为s[] {1,2,3,4,5}的全排列已经从小到大排序,要找出第16个数:
*
* 1. 首先用16-1得到15
*
* 2. 用15去除4! 得到0余15
*
* 3. 用15去除3! 得到2余3
*
* 4. 用3去除2! 得到1余1
*
* 5. 用1去除1! 得到1余0
*
* 有0个数比它小的数是1
*
* 所以第一位是1
*
* 有2个数比它小的数是3,但1已经在之前出现过了所以是4
*
* 有1个数比它小的数是2,但1已经在之前出现过了所以是3
*
* 有1个数比它小的数是2,但1,3,4都出现过了所以是5
*
* 最后一个数只能是2
*
* 所以这个数是14352
*/
public void invKT(int n, int k, int s[]) {
int i, j, t;
int[] vst = new int[8];
k--;
for (i = 0; i < n; i++) {
t = k / fac[n - i - 1];
for (j = 1; j <= n; j++)
if (0 == vst[j]) {
if (t == 0)
break;
t--;
}
s[i] = j;
vst[j] = 1;
k %= fac[n - i - 1];
}
}
/**
* @param args
*/
public static void main(String[] args) {
// int[] s = new int[]{1,2,4};
int[] s = new int[]{3,2,1};
System.out.println(new KangTuo().KangTuo(s.length, s));
}
}
- 【Jfinal源码】第一章 com.jfinal.core.JFinalFilter(1)
- 【ehcache】 timeToLiveSeconds 和 timeToLiveSeconds 的区别
- 升级 CentOS7 、Redis 3.2.x 的问题
- AngularJS 中使用Swiper制作滚动图不能滑动
- JAVA服务端配置允许跨域请求
- CentOS mysql配置主从复制
- Quartz依赖数据库表
- Spring Security Oauth2.0 实现短信验证码登录
- 【Spring Cloud】Redis缓存接入监控、运维平台CacheCloud
- 基于Redis实现分布式应用限流
- Jasypt : 整合spring boot加密应用配置文件敏感信息
- Eureka:扩展ClientFilter实现服务注册自定义过滤
- 【系统日志】log4j配置学习总结
- 【译】MySQL char、varchar的区别
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Apache IoTDB 系列教程-2:基础 SQL 操作
- Apache IoTDB 系列教程-3:部署运维
- 栈论 : 递归与栈式访问,如何用栈实现所有递归操作(幼儿园题目篇)
- kali下安装beef并联合Metasploit
- 初次使用maven创建web工程发现只有一个idea目录,src,webapp目录都不见了,解决方案
- 栈论 : 递归与栈式访问,如何用栈实现所有递归操作(幼儿园题目篇,题目2)
- SQL注入原理及代码分析(一)
- SQL注入原理及代码分析(二)
- 写一个方法,输入一个文件名和一个字符串,统计这个字符串在这个文件中出 现的次数。
- SSRF漏洞简单分析
- 树莓派基础实验30:BMP180气压传感器实验
- DC-1靶机实战和分析
- 如何用Python优雅的登录校园网?
- PHP入门之类型与运算符
- 栈论 : 递归与栈式访问,如何用栈实现所有递归操作(幼儿园题目篇,题目3)