题目:
N个人围成一圈顺序编号,从1号开始按1、2、3......顺序报数,报p者退出圈外,其余的人再从1、2、3开始报数,报p的人再退出圈外,以此类推。
请按退出顺序输出每个退出人的原序号。
输入格式:
输入只有一行,包括一个整数N(1<=N<=3000)及一个整数p(1<=p<=5000)。
输出格式:
按退出顺序输出每个退出人的原序号,数据间以一个空格分隔,但行尾无空格。
输入样例:
在这里给出一组输入。例如:
7 3
输出样例:
3 6 2 7 5 1 4
实现思路:
我认为我的思路不是特别好,但是可以过检测点,感兴趣的可以看看。
先建立一个循环单链表,然后用一个指针str指向当前元素,flag表示当前元素所报的数,要是是3的话,就从链表上删除。
但是,我发现还是运行超时,所以我想要是只剩下一个元素的话,直接输出就可以了,不用再数数了。例如,只剩下一个元素,而要报5000个数,时间就会很长。所以,我写了只剩下一个元素时(即conut等于n-1时)直接输出,当然还要考虑只有一个元素的情况(主要是空格的输出)。
这也是我认为我写得不好的原因,只是为了通过测试点处理的情况。
count表示已经输出的数字,作为终止条件,同时也是是否输出空格的标志。
flag是报的数,flag为3的时候删除当前对象。
str是指针,指向当前报数的对象。
实现代码:
#include <stdio.h>
#include <stdlib.h>
//单链表结构
typedef struct Node {
int data;
struct Node* next;
} LinkList;
//头插法
LinkList * creat(int n) {
LinkList *s, *r, *L;
L = r = NULL;
for (int i = 1; i <= n; i++) {
s = (LinkList*)malloc(sizeof(LinkList));
s->data = i;
if (!L) L = s;
else r->next = s;
r = s;
}
if (r) r->next = L;
return L;
}
int main() {
int n, p;
scanf("%d %d", &n, &p);
LinkList *L = creat(n);
LinkList *str = L;
LinkList *s;
int count = 0;
int flag = 1;
while (count < n) {
str = str->next;
if (count == n - 1 && count != 0) {
printf(" %d", str->data);
break;
}
if (count == n - 1 && count == 0) {
printf("%d", str->data);
break;
}
flag++;
if (flag == p) {
if (count == 0) printf("%d", str->data);
else printf(" %d", str->data);
s = str->next;
str->next = s->next;
str->data = s->data;
free(s);
count++;
flag = 1;
}
}
return 0;
}
标签:count,int,PTA,约瑟夫,next,flag,str,C语言,data
From: https://blog.csdn.net/2302_80273625/article/details/143781604