题目(要求用循环链表实现)
约瑟夫问题是一个经典的问题。已知n个人(不妨分别以编号1,2,3,...,n 代表 )围坐在一张圆桌周围,从编号为 k 的人开始,从1开始顺时针报数1, 2, 3, ...,顺时针数到m 的那个人,出列并输出。然后从出列的下一个人开始,从1开始继续顺时针报数,数到m的那个人,出列并输出,...依此重复下去,直到圆桌周围的人全部出列。
输入:n, k, m
输出:按照出列的顺序依次输出出列人的编号,编号中间相隔一个空格,每10个编号为一行。
非法输入的对应输出如下
a)
输入::n、k、m任一个小于1
输出:n,m,k must bigger than 0.
b)
输入:k>n
输出:k should not bigger than n.
例:
输入:9,3,2
输出:4 6 8 1 3 7 2 9 5
C++完整代码
cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {}
};
int main() {
int n, k, m;
scanf("%d%*c%d%*c%d", &n, &k, &m);
if (n < 1 || k < 1 || m < 1) {
cout << "n,m,k must bigger than 0." << endl;
return 0;
}
if (k > n) {
cout << "k should not bigger than n." << endl;
return 0;
}
// 创建循环链表
ListNode* head = new ListNode(1);
ListNode* cur = head;
for (int i = 2; i <= n; i++) {
cur->next = new ListNode(i);
cur = cur->next;
}
cur->next = head;
// 将cur指针移动到编号为k的节点
for (int i = 0; i < k - 1; i++) {
head = head->next;
}
int count = 0;
// 开始报数并出列
while (n) {
if (m > 1) {// 数到m的前一个节点
for (int i = 0; i < m - 2; i++) {
head = head->next;
}
// 出列并记录编号
ListNode* temp = head->next;
cout<<temp->val;
head->next = temp->next;
head = head->next;
delete temp;
n--;
count++;
}
else {
cout<<head->val;
head = head->next;
n--;
}
if (n == 0 && count % 10 != 0) cout << endl;
else if (count % 10 == 0) cout << endl;
else cout << " ";
}
return 0;
}