Prob_Solve 板


LINE

几年前我在 C_andCPP 版发表了一篇 Josephus problem 的整理 #1AMqP2Cr 。 最近我又重新的研究了一下这问题,在这边跟大家分享一下心得。 问题如下: 有 n 个人围成一圈,并且依序编号为1 ~ n,从 1 开始数,每数 m 个 人就把此人由圈圈中删除,一直持续此动作直到只剩下一个人为止。 问最後被剩下来的那个人是编号几号。 简单的使用 queue 或是 recursion 的解法就不介绍了,一般常见的解 法有四种: 1. Recursion 改成回圈版 [1] int ans = 0; for (int = 2; i <= n; ++i) ans = (ans + m) % i; return ans + 1; 复杂度是 O(n),而这方法也可以找出第 k 个被删除的人的编号。 缺点是不管 m 是大还是小,这方法所需要的时间是一样的。 2. 另一种 recursion 改成的回圈版 版本 1 [3] int answer = n * m; while (answer > n) answer += (answer - n - 1) / (m - 1) - n; return answer; 版本 2 [4] 差别只是在计算方向不同,但是这版本比较慢,因为需要稍多运算。 int d = 1; while (d <= (m - 1) * n) d = 1 + (d * m - 1) / (m - 1); return m * n + 1 - d; 这类方法因为需要计算 n * m 或是 n * (m - 1) ,所以当 n 和 m 都比较大时 会 integer overflow。 复杂度是 O(log_{m/(m-1)} (nm)) 所以当 m 小的时候这方法会快很多,但是当 m 大时就很慢了。 3. 另一种 recursion [2]。 if (n < m) 用方法 2 jn = recursion 算出 (n - floor(n/m), m) 的答案 if (jn <= n % m) return jn + m * (n - floor(n/m)) else jn -= n % m return m * floor(jn / (m - 1)) + (jn % (m-1) == 0 ? -1 : jn % (m - 1)) 复杂度 O(m + lg_{m/(m-1)} (n/m)),但是跟前面的方法不同,这方法 需要额外的空间来作 recursion 。 而且当 m 很大的时候,这方法很容易会 stackoverflow 因为 recursion 太深。 所以需要手动用 stack 模拟 recursion。 4. 方法 3 的回圈版 我发现到 3 的方法其实有两个阶段, 一开始会一直 recusion ,而且过程中 m 是一直不变的,只有 n 值减小。 当 n 比 m 小时,直接使用方法 2 计算出答案,然後一层一层回推出原本 n 的答案。 所以我就尝试着能不能用两个回圈来代替 recursion ,而不使用 stack 。 不过困难点是在於怎样从下层的 n 回推出上层的 n 。 也就是考虑 recursion: (n, m) -> (n' = n - floor(n/m), m) 如何在只知道 n' 和 m 的情况下推出 n 。 不过很可惜的是光靠 n' 和 m 是没办法明确的决定 n 的。 因为 n 可能是 n' + n'/(m - 1) 也可能是 n' + n'/(m - 1) + 1 但是只有这两种可能而已,而且後者发生的机率不高。 所以只要花一些空间纪录 n = n' + n'/(m - 1) + 1 的资讯,在回推的时候就 可以顺利的从 n' 和 m 推出 n 了。 不过我找不到 n = n' + n'/(m - 1) + 1 出现次数的上限, 不然就可以得到空间复杂度的上限了。 实验 我测试了 n = 2^21 的情况。 当 m < 2^10 时,方法 2 最快。 当 2^10 < m < 2^15 方法 4 最快。 当 m > 2^15 ,方法 1 最快,执行时间约为方法 4 的一半。 当 n 接近 m 时,方法 1 的执行时间只有方法 2 的 1/30 。 结论 因为方法 4 本质上还是 recursion , 所以可以把方法 4 的 base case 改成当 cn < m 时使用方法 1 , c 为一个小的正整数,这样的话就可以让方法 4 的速度永远比方法 1 快了。 同理也可以把方法 2 放进去方法 4 的 base 中,得到一个速度永远最快的方法。 [1] D. Woodhouse, "Programming the Josephus problem," ACM SIGCSE Bulletin, Volume 10 Issue 4, December 1978 Pages 56-58 [2] Fatih Gelgi's, "Time Improvement on Josephus Problem" [3] Ronald L. Graham, Donald E. Knuth, Oren Patashnik Concrete Mathematics, Section 3.3 [4] Donald E. Knuth The Art of Computer Programming, Vol. 1: Fundamental Algorithms Section 1.3.3 Exercise 31 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 24.23.200.172
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Prob_Solve/M.1471117368.A.819.html ※ 编辑: FRAXIS (24.23.200.172), 08/16/2016 09:44:02
1F:推 oscar60111: 推一个 感谢整理心得 08/16 18:26







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Tech_Job站内搜寻

TOP