康托展开是什么呢?

(以下内容引自CSDN用户zhongkeli 原文地址:http://blog.csdn.net/zhongkeli/article/details/6966805

其实这位作者也是引用的博客园用户的文章,但是原文已经找不到了,因此放上转载作者作为来源,尊重原作者版权。)

康托展开的公式是 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,ai为当前未出现的元素中是排在第几个(从0开始)。
  这个公式可能看着让人头大,最好举个例子来说明一下。例如,有一个数组 s = ["A", "B", "C", "D"],它的一个排列 s1 = ["D", "B", "A", "C"],现在要把 s1 映射成 X。n 指的是数组的长度,也就是4,所以
X(s1) = a4*3! + a3*2! + a2*1! + a1*0!

关键问题是 a4、a3、a2 和 a1 等于啥?

a4 = "D" 这个元素在子数组 ["D", "B", "A", "C"] 中是第几大的元素。"A"是第0大的元素,"B"是第1大的元素,"C" 是第2大的元素,"D"是第3大的元素,所以 a4 = 3。
a3 = "B" 这个元素在子数组 ["B", "A", "C"] 中是第几大的元素。"A"是第0大的元素,"B"是第1大的元素,"C" 是第2大的元素,所以 a3 = 1。
a2 = "A" 这个元素在子数组 ["A", "C"] 中是第几大的元素。"A"是第0大的元素,"C"是第1大的元素,所以 a2 = 0。
a1 = "C" 这个元素在子数组 ["C"] 中是第几大的元素。"C" 是第0大的元素,所以 a1 = 0。(因为子数组只有1个元素,所以a1总是为0)
所以,X(s1) = 3*3! + 1*2! + 0*1! + 0*0! = 20

对于每一种排列,康托展开后,编号分别为:
A B C | 0
A C B | 1
B A C | 2
B C A | 3
C A B | 4
C B A | 5

说到这里,大家差不多久都明白了吧。康托展开,是用一一对应的方式将一些元素的排列映射为一组从1开始的连续数字。因此,如果在哈希表中用到它,不必取模,计算过程也没有复杂多少,但大大减少了哈希数组的空间复杂度,使得哈希数组空间利用率达到100%。哈希数组大小是n!(n为元素个数)。

那么,我们引用CSDN用户Re_cover的康托展开的代码(源地址:http://blog.csdn.net/re_cover/article/details/9823169):

int factor[] = {1,1,2,6,24,120,720,5040,40320,362880};//阶乘   int cantor(char x[]) //康托展开
{  int sum = 0, s;  for(int i = 0; i < 9; i++)  {  s = 0;  for(int j = i + 1; j < 9; j++)  if(x[j] < x[i])  s++;  sum += s * factor[9 - i - 1];  }  return sum;
}  

通过康托逆展开生成全排列

如果已知 s = ["A", "B", "C", "D"],X(s1) = 20,能否推出 s1 = ["D", "B", "A", "C"] 呢?
因为已知 X(s1) = a4*3! + a3*2! + a2*1! + a1*0! = 20,所以问题变成由 20 能否唯一地映射出一组 a4、a3、a2、a1?如果不考虑 ai 的取值范围,有
3*3! + 1*2! + 0*1! + 0*0! = 20
2*3! + 4*2! + 0*1! + 0*0! = 20
1*3! + 7*2! + 0*1! + 0*0! = 20
0*3! + 10*2! + 0*1! + 0*0! = 20
0*3! + 0*2! + 20*1! + 0*0! = 20
等等。但是满足 0 <= ai <= n-1 的只有第一组。可以使用辗转相除的方法得到 ai,如下图所示:

知道了a4、a3、a2、a1的值,就可以知道s1[0] 是子数组["A", "B", "C", "D"]中第3大的元素 "D",s1[1] 是子数组 ["A", "B", "C"] 中第1大的元素"B",s1[2] 是子数组 ["A", "C"] 中第0大的元素"A",s[3] 是子数组 ["C"] 中第0大的元素"C",所以s1 = ["D", "B", "A", "C"]。
这样我们就能写出一个函数,它可以返回  s 的第 m 个排列。

这里同样引用Re_cover的代码:

void trans(int x) //康托展开逆运算
{  int visit[10] = {0};  int t;  for(int i = 0; i < 9; i++)  {  t = x / factor[9 - i - 1];  x %= factor[9 - i - 1];  for(int j = 0; j <= t; j++)  if(visit[j] == 1)  t++;  visit[t] = 1;  st[i] = t;  }
}  

至此,康托展开的学习就告一段落了。最后想介绍一下康托,虽然估计大家也都认识他吧,格奥尔格·康托,集合论的发明者,一生执着追求的异类。我们的数学老师只发过一篇补充阅读材料,介绍的就是康托。他是幸运的,他求学时,正值柏林大学形成欧洲数学中心的时代,他的导师是大数学家库莫尔,外尔斯特拉斯和克罗内克。他又是不幸的,他的集合论如罗巴切夫斯基的鞍面几何那样不为世人所接受,但罗巴切夫斯基至少还有在内心里默默支持他的高斯,而康托的学说即使他的恩师克罗内克都是最激进的反对者。孤独而执着地坚持着自己的学说的康托最终罹患严重的精神分裂,在痛苦和绝望中死去。直到他死后很多年,人们才重新发现集合论的重要性。如今集合论已成为中学数学最为基础的第一课。让我们缅怀这位抗争一生的数学家。

顺带也缅怀一下同样孤独一生的罗巴切夫斯基,他曾巡回欧洲演讲,然而无人能回应他殷切的期待。正如高斯日记里所说:“当时在场的各位,我或许是其中唯一听懂罗巴切夫斯基先生在说什么的人。”然而高斯的软弱和怯懦让他没有勇气公开支持这一在他内心已然成熟却被视为异端的理论,这让罗氏进一步陷入冰窖,仿佛这一成果成了他一生的污点。最让我感动的是,尽管孤独落寞,他至死都坚信这一成果的正确性,坚信这是一种独立于欧式几何的几何系统。

相比之下,黎曼的境遇就要好上很多。在人们的思想进一步解放后,年轻的波恩哈德·黎曼(时年28岁)拿着一篇赫然写着平行线可以相交的论文来到歌厅根大学,当即被聘为讲师。(北师大的老教授在这里吐槽说由此可见当时德国大学数学是什么样的水平= =好喜欢萌哒哒老爷爷)这篇论文奠定了黎曼几何的基础。黎曼几何是球面几何,与罗氏几何的鞍面不同,但产生的影响愈发广大。它深刻地影响了拓扑学,在爱因斯坦以它为基础发明广义相对论后更是被世人奉若珍宝。而罗巴切夫斯基也终于得以正名。

好了,科学史就说到这里吧。仰望满天的星空,缅怀逝去的先辈,让我们努力为人类科学进步做出更大的努力。

——千里之行,始于足下。

【日常学习】【数学/哈希】康托展开相关推荐

  1. 数学--数论--康托展开与逆康托展开

    康托展开 可以理解为把一个全排列映射到一个数上面,因为全排列如果按照从小到大或者从大到小,肯定是有一个确定的序列的. 一般是从小到大的序列个数.我们就是要求出这个序列的位置.,想法很简答,就是求出前面 ...

  2. A_Star 康托展开 八数码问题

    A_Star算法是一个主要用bfs实现的寻路算法,当数据量庞大的时候往往有更高的时间效率,可以看成是Dijkstra算法的升级版. "盲目搜索会浪费很多时间和空间, 所以我们在路径搜索时, ...

  3. 【BZOJ】3301: [USACO2011 Feb] Cow Line(康托展开)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3301 其实这一题很早就a过了,但是那时候看题解写完也是似懂非懂的.... 听zyf神犇说是康托展开, ...

  4. 【数学】Why Study Math 为什么学习数学

    看到下面的一些评论,很感动: You know, in CHina,most of people know how to learn mathmatics. But few of them know ...

  5. 我为什么重新开始学习数学?

    我为什么重新开始学习数学? 突然觉得自己真是可笑至极,到今天我还没有明白为什么要学习.在学校学习数学,开始的时候还算跟得上,也不是特讨厌.慢慢地 x,y等符号越来越多,公式繁多,表述起来越来越复杂,自 ...

  6. [总结] 康托展开及其逆运算

    这里先贴一道例题 我们先科普一下康托展开 定义: X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! ai为整数,并且0<=ai<i ...

  7. 康托展开与逆展开(原理+模板)

    定义: 康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩. 康托展开的实质是计算当前排列在所有由小到大全排列中的名次,因此是可逆的. 原理: 代表在位置i后面且小于的值得个数 (n ...

  8. 康托展开与八数码问题

    康托展开的公式是 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,ai为当前未出现的元素中是排在第几个(从0开始). 用康托展开将排列 ...

  9. LeetCode 60. 第k个排列(回溯 康托展开)

    文章目录 1. 题目 2. 解题 2.1 回溯 2.2 数学-康托展开 1. 题目 给出集合 [1,2,3,-,n],其所有元素共有 n! 种排列. 按大小顺序列出所有排列情况,并一一标记,当 n = ...

最新文章

  1. mysql 单标递归_MySql整理篇之递归
  2. 风控算法最常见的知识WOE讲解!
  3. linux的cpu信息怎么理解,理解Linux下的CPU信息:lscpu cpuinfo
  4. 二进制逆向工程师_利用Ghidra逆向分析Go二进制程序(下篇)
  5. python opencv 直方图均衡_详解python OpenCV学习笔记之直方图均衡化
  6. 第二十三篇:在SOUI中使用LUA脚本开发界面
  7. int fun(int x){int p;if(x == 0 || x==1) return p=3;else p = x-fun(x-2);}void main(){printf(“%d\n“)}
  8. (转)虚拟货币交易所时代结束
  9. java聊天室系统用例图_java聊天室的设计与实现.ppt
  10. 大数据前端个人提升与团队规划
  11. 招投标信息爬虫 (只上最简单的版本,仅用于技术交流)
  12. vp9 prob 详细分析
  13. 用户标签(三):oneid与用户标签之间的相互打通 实现用户标签
  14. StellarWP 收购 LearnDash 学习管理系统
  15. Pytorch报错:“freeze_support()“ line can be omitted if the program is not going to be frozen(已解决)
  16. 【原创】简单介绍 Windows XP 中的chkdsk(checkdisk磁盘检查)工具
  17. 十三、添加RD 会话主机角色
  18. 明翰游记V1.7(持续更新)
  19. 效率神器----QuickLook
  20. 猫狗大战使用CNN分类

热门文章

  1. Android的UI卡顿
  2. Python学习基础
  3. 独家! 11省/直辖市,未来三年5G“重要应用项目”建设清单汇总
  4. 5G的到来,对IDC行业的影响
  5. android无限级树形控件,无限分类树,无限层级树
  6. spring data 系类的封装框架开源
  7. 【实战演练】Ceph分布式存储系列02-Ceph分布式存储的3种使用方式
  8. 邮件服务器MailServer之 Hibernate持久层开发
  9. Cerebral Cortex:衰老调节由执行控制训练引起的前额可塑性
  10. 计算机控制技术 王书锋,研究生导师王书锋:郑州大学