I
第一种方法代码:
#include <stdio.h>
#include <malloc.h>
#define N 9
#define doom 4
void lowJoseph(int num, int doomLength);
void lowJoseph(int num, int doomLength) {
int alive = N; //存活人数
int *circle = NULL; //定义一个数组,里面元素值均为0
int index = 0; //令初始下标为0
int ss = 0; //进行数数
circle = (int*)calloc(sizeof(int), num);
while(alive > 0) { //只要有幸存者,就继续出圈
ss += 1 - circle[index];
if(ss == doomLength) { //如果数数到这个人,进行下列操作
printf("%d ", index + 1); //输出这个人的序号
circle[index] = 1; //将这个人状态改为出圈状态
alive--; //圈内存活的人数减一
ss = 0; //报数从0重新开始
}
index = (index + 1) % num; //下标+1,即轮到下一个人,但因为圈是循环的,因此与圈最大人数取余
//当数到圈内最后一个人时,重新从第一个人开始
}
free(circle); //所有人出圈后,释放内存
}
int main() {
lowJoseph(N, doom);
}
第一种方法虽然好理解,但是很耗费时间,因为出圈之后的人还需要参与判断(判断元素值是否为0才能选择进行的操作),而第二种方法,如果该人出圈,则下一次操作直接略过此人,在操作人数很多的时候,这会大大减少运行时间!
第二种方法代码:
#include <stdio.h>
#include <malloc.h>
#define N 9
#define doom 4
void middleJoseph(int num, int doomLength);
void middleJoseph(int num, int doomLength) {
int alive = num; //存活人数
int count = 0; //计数器
int curIndex = 0; //当前人下标
int preIndex = num - 1; //前一个人是下标
int *circle = NULL;
int index;
circle = (int *)calloc(sizeof(int), num); //申请一个空间
for(index = 0; index < num; index++) { //初始化链表
circle[index] = (index + 1) % num;
}
while(alive > 0) { //当圈内还有人
count++; //计数
if(doomLength == count) { //当计数大小与厄运数字相同时,进行出圈操作
//出圈要进行的操作
printf("%d ", curIndex + 1); //输出出圈人的位置
alive--; //将存活的人数减一
count = 0; //计数器置零
circle[preIndex] = circle[curIndex]; //真正的出圈操作
} else {
preIndex = curIndex; //继续处理下一个人
}
curIndex = circle[curIndex]; //当前人向后移动
}
printf("\n");
free(circle); //释放链表
}
int main() {
middleJoseph(N, doom);
}
第二段代码,在进行时,一定要认真进行一次变量跟踪,不然会不好理解
如果有错误的话,还希望大家多多指教~