n n n 个人围成一圈,从第一个人开始报数,数到 m m m 的人出列,再由下一个人重新从 1 1 1 开始报数,数到 m m m 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。
注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰 n ? 1 n-1 n?1 名小朋友,而该题是全部出圈。
输入两个整数 n , m n,m n,m。
输出一行 n n n 个整数,按顺序输出每个出圈人的编号。
10 3
3 6 9 2 7 1 8 5 10 4
1 ≤ m , n ≤ 100 1 \le m, n \le 100 1≤m,n≤100
使用预先分配的一段连续空间存储链表,具体有两种做法:
#include <bits/stdc++.h>
const int N = 105;
struct node{
int id,nextid;
//int data; //根据具体情况定义数据data
}nodes[N];
int main() {
int n,m;
scanf("%d %d",&n,&m);
nodes[0].nextid = 1;
for (int i = 0; i <= n; ++i) {
nodes[i].id = i;
nodes[i].nextid = i+1;
}
nodes[n].nextid = 1;
int now = 1, prev = 1;
while((n--)>1){
for (int i = 1; i < m; ++i) {
prev = now;
now = nodes[now].nextid;
}
printf("%d ",nodes[now].id);
nodes[prev].nextid = nodes[now].nextid;
now = nodes[prev].nextid;
}
printf("%d",nodes[now].nextid);
return 0;
}
② 双向静态链表
#include <bits/stdc++.h>
const int N = 105;
struct node{
int id,nextid,preid;
//int data; //根据具体情况定义数据data
}nodes[N];
int main(){
int n,m;
scanf("%d %d",&n,&m);
nodes[0].nextid = 1;
for (int i = 1; i <= n; ++i) {
nodes[i].id = i;
nodes[i].preid = i-1;
nodes[i].nextid = i+1;
}
nodes[n].nextid = 1;
nodes[1].preid = n;
int now = 1;
while((n--)>1){
for (int i = 1; i < m; ++i)
now = nodes[now].nextid;
printf("%d ",nodes[now].id);
int prev = nodes[now].preid;
int next = nodes[now].nextid;
nodes[prev].nextid = nodes[now].nextid;
nodes[next].preid = nodes[now].preid;
now = next;
}
printf("%d",nodes[now].nextid);
return 0;
}
定义一个一维数组nodes[ ],其中nodes[ i ]的 i 就是结点的值,而nodes[ i ]的值是下一个结点。
优点:简单,书写方便
缺点:一个结点只能存放一个数据,扩展性差
#include <bits/stdc++.h>
int nodes[150];
int main(){
int n,m;
scanf("%d %d",&n,&m);
for (int i = 1; i <= n-1; ++i)
nodes[i] = i+1;
nodes[n] = 1;
int now = 1, prev = 1;
while((n--)>1){
for (int i = 1; i < m; ++i) {
prev = now;
now = nodes[now];
}
printf("%d ",now);
nodes[prev] = nodes[now];
now = nodes[prev];
}
printf("%d",now);
return 0;
}