算法导论14-2习题解答 Josephus排列(约瑟夫环)
2012-05-10 14:01
1061 查看
CLRS 14-2 Josephus问题的定义如下:假设n个人排成环形,且有以正整数m<=n。从某个制定的人开始,沿环报数,每遇到第m个人就让其出列,且报数进行下去。这个过程一直进行到所有人都出列为止。每个人出列的次序定义了整数1,2,...,n的(n, m)-Josephus排列。例如,(7,3)-Josephus排列为<3,6,2,7,5,1,4>。
a)假设m为整数。请描述一个O(n)时间的算法,使之对给定的整数n,输出(n, m)-Josephus排列。
b)假设m不是个常数。请描述一个O(nlgn)时间的算法,使给定的整数n和m,输出(n, m)-Josephus排列。
解答:
a)首先,我们很容易想到用一个循环链表,即最后一个结点指向头结点的单链表。然后,选定一个结点,走m步,输出此结点的值,然后删除之,然后再走m步,依次循环下去,由于建立链表时间为O(n),而删除的过程为O(m*n),由于m为常数,故总的时间复杂度为O(n)。
(伪)伪代码:
b)第二问,由于在这一章,所以会采用基于红黑树的顺序统计树。
这里可以结合着伪代码和下面的例子看整个流程是怎么走的。
(伪)伪代码:
我们来对数组{1,2,3,4,5,6,7}走一遍,我们选择第一个数为起始点,i=1,选择m=3,则
i = (i+m-2)%(n--) + 1 = 3,好的,输出第3个数,即3,然后去除3,剩下{1,2,4,5,6,7},n=6接着
i = (i+m-2)%(n--) + 1 = 5,好的,输出第5个数(这里不是5,在树中剩下的元素中,是第五小的数),即为6,然后删除6,现在剩下元素为{1,2,4,5,7},n=5,接着
i = (i+m-2)%(n--) + 1 = 2,好的,输出第2个数,即为2,然后删除2,现在剩下元素为{1,4,5,7},n=4,接着
i = (i+m-2)%(n--) + 1 = 4,输出第四个数,即为7,然后删除7,现在剩下元素为{1,4,5},n=3,接着
......
我们发现,这个算法的执行是正确的。
a)假设m为整数。请描述一个O(n)时间的算法,使之对给定的整数n,输出(n, m)-Josephus排列。
b)假设m不是个常数。请描述一个O(nlgn)时间的算法,使给定的整数n和m,输出(n, m)-Josephus排列。
解答:
a)首先,我们很容易想到用一个循环链表,即最后一个结点指向头结点的单链表。然后,选定一个结点,走m步,输出此结点的值,然后删除之,然后再走m步,依次循环下去,由于建立链表时间为O(n),而删除的过程为O(m*n),由于m为常数,故总的时间复杂度为O(n)。
(伪)伪代码:
//i为起始点 1 PROCESS(list, i) { node = list.get(i); while (list != NULL) { for (i = 0; i < m-1; i++) { node = node->link; } tmp = node;//保存node的副本 print node->key;//输出值 node = node->link;//在删除之前指向下一个结点 delete tmp;//从链表删除,当然,之前还有指针之间的链接转变 } }
b)第二问,由于在这一章,所以会采用基于红黑树的顺序统计树。
这里可以结合着伪代码和下面的例子看整个流程是怎么走的。
(伪)伪代码:
//建立顺序统计树,在题设中,原始数据是一个排好序的数组,即{1,2,3...n} CreateTree() { for (i = 1; i <= n; i++) insert(T, node[i]);//node存储的是数组元素 } //T为顺序统计树,i为选择的起始点,这里的i表示的是位置,不是node里面的key值,可以理解为第i小的数 Process(T, i) { while (T != NULL) { i = (i+m-2)%(n--) + 1;//在这里,我们不用(i+m-1)%(n--),是因为这个表达式可能计算的结果等于0,但i != 0; print key[OS-SELECT(T, i)]; OS-DELETE(T, i); } }
我们来对数组{1,2,3,4,5,6,7}走一遍,我们选择第一个数为起始点,i=1,选择m=3,则
i = (i+m-2)%(n--) + 1 = 3,好的,输出第3个数,即3,然后去除3,剩下{1,2,4,5,6,7},n=6接着
i = (i+m-2)%(n--) + 1 = 5,好的,输出第5个数(这里不是5,在树中剩下的元素中,是第五小的数),即为6,然后删除6,现在剩下元素为{1,2,4,5,7},n=5,接着
i = (i+m-2)%(n--) + 1 = 2,好的,输出第2个数,即为2,然后删除2,现在剩下元素为{1,4,5,7},n=4,接着
i = (i+m-2)%(n--) + 1 = 4,输出第四个数,即为7,然后删除7,现在剩下元素为{1,4,5},n=3,接着
......
我们发现,这个算法的执行是正确的。
相关文章推荐
- 算法导论-14-2-Josephus排列
- 随机排列算法及《算法导论》5.3节习题解答
- 算法导论-14-2-Josephus排列
- 算法导论-14-2-Josephus排列
- 算法导论 14-2 Josephus 排列
- 算法导论9.1-1习题解答(二叉树)
- 算法导论9.3-8习题解答(类似二分查找算法)
- 算法导论6.5-8习题解答(最小堆K路合并)
- (搬运)《算法导论》习题解答 Chapter 22.1-1(入度和出度)
- JavaSe基础XX14——习题解答_1
- JavaSe基础XX14——习题解答_2
- 算法导论9.3-9习题解答(寻找中位数)
- 算法导论13-1节习题解答
- 走台阶 OR 台阶走——《狂人C》习题解答14(第三章习题4)
- [置顶] 《算法导论》习题解答搬运&&学习笔记 索引目录
- 《算法导论(第2版)》第20章习题解答
- 《C++ Primer》第五版课后习题解答_第五章(2)(09-14)
- 《算法导论》第二章习题解答
- 《算法导论》 - 第6章 - 堆排序 - 习题解答
- 《算法导论》第二章习题解答