题目描述:
题目描述
n (n<=100)个学生排队报数,编号为1到n,然后从1数到3循环报数,每次数到3的人就退出,最后留下来的是编号多少的学生。比如,总共4名学生,编号为1,2,3,4。第一次报数1(报数1),2(报数2),3(报数3),4(报数1),3号退出,第二次报数1(报数2),2(报数3),4(报数1),2号退出,依此类推,直到只剩1名学生,输出其编号。
示例输入1
4
示例输出1
1
示例输入2
10
示例输出2
4
算法:
思路:
代码实现:
# include<stdio.h>
int main(){
int n,k=1,i=0;
scanf("%d",&n);
int count=n,end;
int nums[n];
for(int i=0;i<n;i++){
nums[i]=i+1;
}
while(count>1){
//报数
if(nums[i]!=0){
nums[i]=k++;
}
//报数的值重置
if(k>3){
k=1;
}
//移除报数为3的数
if(nums[i]==3){
nums[i]=0;//置为0,之后不再报数
count--;//计数减一
}
//返回到第一个数
i++;
if(i==n){
i=0;
}
}
for(int j=0;j<n;j++){
if(nums[j]!=0){
printf("%d\n",j+1);
}
}
}
算法优化:
思路:
1与0标记是否移除,更为易懂
代码实现:
#include <stdio.h>
#define MAX_STUDENTS 100
int findLastStudent(int n);
int main() {
int n;
// 获取学生总数
scanf("%d", &n);
// 找出最后留下的学生编号
int lastStudent = findLastStudent(n);
printf("%d\n", lastStudent);
return 0;
}
int findLastStudent(int n) {
// 创建数组表示学生是否已经退出
int students[MAX_STUDENTS];
for (int i = 0; i < n; i++) {
students[i] = 1; // 初始化为未退出
}
int count = 0; // 记录报数次数
int index = 0; // 数到3的学生索引
while (1) {
// 数到3的学生退出
if (students[index] == 1) {
count++;
if (count == 3) {
students[index] = 0; // 标记为已退出
count = 0; // 重新开始报数
}
}
// 移动到下一个学生
index++;
// 判断是否回到队伍开头
if (index == n) {
index = 0;
}
// 检查是否只剩下一个学生
int remainingStudents = 0;
int lastStudent = 0;
for (int i = 0; i < n; i++) {
if (students[i] == 1) {
remainingStudents++;
lastStudent = i + 1; // 记录最后一个学生的编号(不断更新)
}
}
if (remainingStudents == 1) {//只剩一个学生时,返回编号
return lastStudent;
}
}
}