《C算法》读书笔记 (4):Hello,Joseph!
来源:互联网 发布:欢乐升级mac版 编辑:程序博客网 时间:2024/04/29 07:35
P67, 3-8 约瑟夫问题
上一篇文章中提到了使用链表模拟约瑟夫问题求解。约瑟夫问题是这样的 :假设有N个人决定选出一名领导,将所有人排成一个圆周,从1编号到N。现在从1开始,数M个人,最后的M出列。重复上述步骤,直到只剩下一个人,该人即为领导。
首先定义链表的数据结构:
typedef struct node *link;struct node { int item; link next;};
将node称为节点。现要删除节点p->next,只需要使p->next=p->next->next。
void sim_joseph() // 链表模拟{ link p, t; t = p = (link)malloc(sizeof(node)), p->item = 1, p->next = p; for(int i = 2; i <= n; ++ i) { p = (p->next = (link)malloc(sizeof(node))); p->item = i; } p->next = t; for(int i = 0; i < n - 1; ++ i) // n - 1 times execute { for(int j = 0; j < m - 1; ++ j) p = p->next; //printf("%d is killed\n", p->next->item); t = p->next; p->next = p->next->next; free(t); } printf("%d remains alive\n", p->item); free(p);}
显然,该算法的复杂度为
有没有更好的算法?答案是肯定的。
假设有一个N=6,M=2的样例,也就是6个人围成一圈,每次报2个数,直到最后一个人。
样例的流程如下:
为了便于理解,我们将N=6,5,4时的最后一个人先利用链表法计算出来:
N=5,M=2时,最后的结果为3,记
同理得,
将所有编号减1(为了计算的简便性,此时
在1号选手被淘汰出局后,剩下的五人实际上重新组成了一个新的约瑟夫问题
其中
易见,在5人问题中最后的胜者2,在6人问题中编号为4。
同理,在4人问题中最后的胜者1,在5人问题中编号为3。
如此递推,存在边界:1人问题最后胜者为0。从1人问题依次反推就得到解。
该算法的复杂度为
完整的程序如下:
#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>using namespace std;typedef struct node *link;struct node { int item; link next;};int n, m;void linear_joseph() // 递推{ int ans = 0; for(int i = 2; i <= n; ++ i) { ans = (ans + m) % i; } printf("linear shows %d remains alive\n", ans + 1);}void sim_joseph() // 链表模拟{ link p, t; t = p = (link)malloc(sizeof(node)), p->item = 1, p->next = p; for(int i = 2; i <= n; ++ i) { p = (p->next = (link)malloc(sizeof(node))); p->item = i; } p->next = t; for(int i = 0; i < n - 1; ++ i) // n - 1 times execute { for(int j = 0; j < m - 1; ++ j) p = p->next; //printf("%d is killed\n", p->next->item); t = p->next; p->next = p->next->next; free(t); } printf("sim shows %d remains alive\n", p->item); free(p);}int main(){ freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); while(scanf("%d%d", &n, &m) != EOF) { sim_joseph(); linear_joseph(); } return 0;}
0 0
- 《C算法》读书笔记 (4):Hello,Joseph!
- Joseph算法,
- JOSEPH.C
- 算法题-约瑟夫(Joseph)问题求解
- 《C算法》读书笔记 (2):约瑟夫
- 《C算法》读书笔记(6):词法分析
- 算法: 约瑟夫问题(Joseph Problem)的分析
- 算法导论读书笔记(4)
- 简单算法之—Joseph
- joseph算法多文件实现
- C算法 读书笔记 第三章
- c++primer读书笔记(4)
- <<Effective C++>>读书笔记(4)
- 约瑟夫环(joseph)
- hdu 1222(Joseph)
- poj 2244 (Joseph)
- 约瑟夫(Joseph)问题
- Joseph(1443)
- 黑马程序员——多线程(上)——第11天
- HDU 5301(Buildings-贪心构造)
- HDU 5391 Zball in Tina Town
- 实模式和保护模式
- 【您的凭证不工作】win7远程桌面提示,请输入新凭据。登录没有成功
- 《C算法》读书笔记 (4):Hello,Joseph!
- linux下进程的最大线程数、进程最大数、进程打开的文件数
- 1151 - Buy or Build (最小生成树)
- 股市风暴下的雪球架构改造经验分享
- poj 3683 2-sat
- Mac下解决Android studio真机调试时无法识别魅蓝手机问题
- 周报1
- oracle10g安装时报"无法确定主机的IP地址时产生异常错误"
- 剑指offer 算法(栈和队列 查找和排序)