环形链表的约瑟夫问题
题目描述
据说著名犹太历史学家 Josephus 有过以下故事:在罗马人占领乔塔帕特后,39 个犹太人与 Josephus 及他的朋友躲到一个洞中,39 个犹太人决定宁愿死也不要被敌人抓到,于是决定了一种自杀方式,41 个人排成一个圆圈,由第 1 个人开始报数,报数到 3 的人就自杀,然后再由下一个人重新报 1,报数到 3 的人再自杀,这样依次下去,直到剩下最后一个人时,那个人可以自由选择自己的命运。这就是著名的约瑟夫问题。现在请用单向环形链表得出最终存活的人的编号。
输入描述:
一行两个整数 n 和 m, n 表示环形链表的长度, m 表示每次报数到 m 就自杀。
输出描述:
输出最后存活下来的人编号(编号从1开始到n)
示例1
输入
5 2
输出
3
备注:
1 ≤ n , m ≤ 10000 1 leq n,m leq 10000 1≤n,m≤10000
题解:
题目要求用单向环形链表,那就用呗。。。循环遍历 n-1 次,每次数到第 m 个人就杀掉,模拟就行,就是时间复杂度有点高。。。
代码:
#include <cstdio>
using namespace std;
struct list_node{
int val;
struct list_node * next;
};
list_node * input_list(int n)
{
list_node * phead = new list_node();
list_node * cur_pnode = phead;
for (int i = 1; i <= n; ++i) {
if (i == 1) {
cur_pnode->val = i;
cur_pnode->next = NULL;
}
else {
list_node * new_pnode = new list_node();
new_pnode->val = i;
new_pnode->next = NULL;
cur_pnode->next = new_pnode;
cur_pnode = new_pnode;
}
}
cur_pnode->next = phead;
return phead;
}
int josephusKill(list_node*& head, int m) {
if (head->next == head || m < 1) return head->val;
list_node *p = head, *pre = NULL;
while (p->next != p) {
for (int i = 1; i < m; ++i) {
pre = p;
p = p->next;
}
pre->next = p->next;
p = pre->next;
}
return p->val;
}
int main(void) {
int n, m;
scanf("%d%d", &n, &m);
list_node * phead = input_list(n);
printf("%d
", josephusKill(phead, m));
return 0;
}
上一篇:
IDEA上Java项目控制台中文乱码
